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
use backend::*;
use rand;
use std::collections::HashMap;
use std::mem::swap;
use Result;

impl<'env, T: rand::Rng> MutTxn<'env, T> {
    fn collect_up_context_repair(
        &self,
        branch: &Branch,
        key: Key<PatchId>,
        patch_id: PatchId,
        edges: &mut HashMap<Key<PatchId>, Edge>,
    ) {
        debug!("collect up {:?}", key);
        let edge = Edge::zero(EdgeFlags::PARENT_EDGE | EdgeFlags::PSEUDO_EDGE);
        for (k, v) in self.iter_nodes(branch, Some((key, Some(&edge))))
            .take_while(|&(k, v)| {
                k == key
                    && v.flag
                        <= EdgeFlags::PARENT_EDGE | EdgeFlags::PSEUDO_EDGE | EdgeFlags::FOLDER_EDGE
                    && v.introduced_by == patch_id
            }) {
            if !edges.contains_key(&k) {
                edges.insert(k.to_owned(), v.to_owned());

                self.collect_up_context_repair(branch, v.dest, patch_id, edges)
            }
        }
    }

    fn collect_down_context_repair(
        &self,
        branch: &Branch,
        key: Key<PatchId>,
        patch_id: PatchId,
        edges: &mut HashMap<Key<PatchId>, Edge>,
    ) {
        debug!("collect down {:?}", key);

        let edge = Edge::zero(EdgeFlags::PSEUDO_EDGE);
        for (k, v) in self.iter_nodes(branch, Some((key, Some(&edge))))
            .take_while(|&(k, v)| {
                k == key && v.flag <= EdgeFlags::PSEUDO_EDGE | EdgeFlags::FOLDER_EDGE
                    && v.introduced_by == patch_id
            }) {
            if !edges.contains_key(&k) {
                edges.insert(k.to_owned(), v.to_owned());

                self.collect_down_context_repair(branch, v.dest, patch_id, edges)
            }
        }
    }

    pub fn remove_up_context_repair(
        &mut self,
        branch: &mut Branch,
        key: Key<PatchId>,
        patch_id: PatchId,
        edges: &mut HashMap<Key<PatchId>, Edge>,
    ) -> Result<()> {
        self.collect_up_context_repair(branch, key, patch_id, edges);
        for (mut k, mut v) in edges.drain() {
            debug!("remove {:?} {:?}", k, v);

            self.del_nodes(branch, k, Some(&v))?;
            swap(&mut k, &mut v.dest);
            v.flag.toggle(EdgeFlags::PARENT_EDGE);
            self.del_nodes(branch, k, Some(&v))?;
        }

        Ok(())
    }

    pub fn remove_down_context_repair(
        &mut self,
        branch: &mut Branch,
        key: Key<PatchId>,
        patch_id: PatchId,
        edges: &mut HashMap<Key<PatchId>, Edge>,
    ) -> Result<()> {
        self.collect_down_context_repair(branch, key, patch_id, edges);
        for (mut k, mut v) in edges.drain() {
            self.del_nodes(branch, k, Some(&v))?;
            swap(&mut k, &mut v.dest);
            v.flag.toggle(EdgeFlags::PARENT_EDGE);
            self.del_nodes(branch, k, Some(&v))?;
        }

        Ok(())
    }
}