1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
use std::{collections::HashMap, time::Duration};
use crate::driver::Driver;
use crate::error::{Error, ErrorKind};
use crate::guid::Guid;
use crate::merge::{Merger, Deletion, StructureCounts};
use crate::tree::{Content, MergedDescendant, Tree};
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct Stats {
pub timings: MergeTimings,
pub counts: StructureCounts,
}
#[derive(Clone, Debug, Default, Eq, PartialEq)]
pub struct MergeTimings {
pub fetch_local_tree: Duration,
pub fetch_new_local_contents: Duration,
pub fetch_remote_tree: Duration,
pub fetch_new_remote_contents: Duration,
pub merge: Duration,
pub apply: Duration,
}
#[macro_export]
macro_rules! time {
($timings:ident, $name:ident, $op:expr) => {{
let now = std::time::Instant::now();
let result = $op;
$timings.$name = now.elapsed();
result
}};
}
pub trait Store<D: Driver, E: From<Error>> {
fn fetch_local_tree(&self) -> Result<Tree, E>;
fn fetch_new_local_contents(&self) -> Result<HashMap<Guid, Content>, E>;
fn fetch_remote_tree(&self) -> Result<Tree, E>;
fn fetch_new_remote_contents(&self) -> Result<HashMap<Guid, Content>, E>;
fn apply<'t>(&mut self, descendants: Vec<MergedDescendant<'t>>,
deletions: Vec<Deletion>) -> Result<(), E>;
fn merge(&mut self, driver: &D) -> Result<Stats, E> {
let mut merge_timings = MergeTimings::default();
let local_tree = time!(merge_timings, fetch_local_tree, {
self.fetch_local_tree()
})?;
debug!(driver, "Built local tree from mirror\n{}", local_tree);
let new_local_contents = time!(merge_timings, fetch_new_local_contents, {
self.fetch_new_local_contents()
})?;
let remote_tree = time!(merge_timings, fetch_remote_tree, {
self.fetch_remote_tree()
})?;
debug!(driver, "Built remote tree from mirror\n{}", remote_tree);
let new_remote_contents = time!(merge_timings, fetch_new_remote_contents, {
self.fetch_new_remote_contents()
})?;
let mut merger = Merger::with_driver(driver, &local_tree,
&new_local_contents, &remote_tree,
&new_remote_contents);
let merged_root = time!(merge_timings, merge, merger.merge())?;
debug!(driver, "Built new merged tree\n{}\nDelete Locally: [{}]\nDelete Remotely: [{}]",
merged_root.to_ascii_string(),
merger.delete_locally.iter().map(Guid::as_str).collect::<Vec<_>>().join(", "),
merger.delete_remotely.iter().map(Guid::as_str).collect::<Vec<_>>().join(", "));
if !merger.subsumes(&local_tree) {
Err(E::from(ErrorKind::UnmergedLocalItems.into()))?;
}
if !merger.subsumes(&remote_tree) {
Err(E::from(ErrorKind::UnmergedRemoteItems.into()))?;
}
let descendants = merged_root.descendants_with_size_hint(
Some(merger.structure_counts.merged_nodes));
let deletions = merger.deletions().collect::<Vec<_>>();
time!(merge_timings, apply, self.apply(descendants, deletions))?;
Ok(Stats { timings: merge_timings, counts: merger.structure_counts.clone() })
}
}