1
1
use crate :: pristine:: * ;
2
2
use crate :: { HashMap , HashSet } ;
3
- use std:: cell:: RefCell ;
4
- use std:: rc:: Rc ;
5
3
6
- type Alive = Rc < RefCell < HashSet < Vertex < ChangeId > > > > ;
7
-
8
- pub ( crate ) fn find_alive_down < T : GraphTxnT > (
4
+ /// The following is an unrolled DFS, where each alive vertex is
5
+ /// inserted into each "alive set" along the current path (which is
6
+ /// recognised by looking at the visited vertices on the stack).
7
+ pub ( crate ) fn find_alive_down < ' a , T : GraphTxnT > (
9
8
txn : & T ,
10
9
channel : & T :: Graph ,
11
10
vertex0 : Vertex < ChangeId > ,
12
- cache : & mut HashMap < Vertex < ChangeId > , Alive > ,
13
- ) -> Result < Alive , BlockError < T :: GraphError > > {
14
- let mut stack = vec ! [ SerializedEdge :: empty( vertex0. start_pos( ) , ChangeId :: ROOT ) ] ;
11
+ cache : & ' a mut HashMap < Vertex < ChangeId > , Option < HashSet < Vertex < ChangeId > > > > ,
12
+ ) -> Result < & ' a Option < HashSet < Vertex < ChangeId > > > , BlockError < T :: GraphError > > {
13
+ let mut stack: Vec < ( _ , Option < HashSet < Vertex < ChangeId > > > ) > = vec ! [ (
14
+ SerializedEdge :: empty( vertex0. start_pos( ) , ChangeId :: ROOT ) ,
15
+ None ,
16
+ ) ] ;
15
17
let mut visited = HashSet :: default ( ) ;
16
- let alive = Rc :: new ( RefCell :: new ( HashSet :: new ( ) ) ) ;
17
- while let Some ( elt) = stack. pop ( ) {
18
- if !visited. insert ( elt. dest ( ) ) {
18
+ while let Some ( ( elt, alive) ) = stack. pop ( ) {
19
+ if let Some ( alive) = alive {
20
+ // We've gone through all the descendants, put this in the
21
+ // cache.
22
+ let vertex = txn. find_block ( & channel, elt. dest ( ) ) ?;
23
+ cache. insert ( * vertex, Some ( alive. clone ( ) ) ) ;
24
+ if stack. is_empty ( ) {
25
+ // Done!
26
+ return Ok ( cache. get ( & vertex0) . unwrap ( ) ) ;
27
+ }
19
28
continue ;
29
+ } else {
30
+ if !visited. insert ( elt. dest ( ) ) {
31
+ continue ;
32
+ }
33
+ stack. push ( ( elt, Some ( HashSet :: new ( ) ) ) ) ;
20
34
}
21
35
let vertex = txn. find_block ( & channel, elt. dest ( ) ) ?;
22
36
if let Some ( c) = cache. get ( vertex) {
23
- alive. borrow_mut ( ) . extend ( c. borrow ( ) . iter ( ) . cloned ( ) ) ;
37
+ for st in stack. iter_mut ( ) {
38
+ if let Some ( ref mut st) = st. 1 {
39
+ if let Some ( c) = c {
40
+ st. extend ( c. iter ( ) . cloned ( ) ) ;
41
+ } else {
42
+ st. insert ( * vertex) ;
43
+ }
44
+ }
45
+ }
24
46
continue ;
25
- } else {
26
- cache. insert ( * vertex, alive. clone ( ) ) ;
27
47
}
28
48
debug ! ( "elt = {:?}, vertex = {:?}" , elt, vertex) ;
29
49
let elt_index = stack. len ( ) ;
@@ -39,60 +59,94 @@ pub(crate) fn find_alive_down<T: GraphTxnT>(
39
59
&& !v. flag ( ) . contains ( EdgeFlags :: PSEUDO )
40
60
{
41
61
if * vertex == vertex0 {
42
- assert ! ( alive. borrow( ) . is_empty( ) ) ;
43
- return Ok ( alive) ;
62
+ // vertex0 is alive.
63
+ stack. truncate ( elt_index) ;
64
+ let ( _, alive) = stack. pop ( ) . unwrap ( ) ;
65
+ let alive = alive. unwrap ( ) ;
66
+ assert ! ( alive. is_empty( ) ) ;
67
+ cache. insert ( vertex0, None ) ;
68
+ return Ok ( cache. get ( & vertex0) . unwrap ( ) ) ;
44
69
} else {
45
- alive. borrow_mut ( ) . insert ( * vertex) ;
70
+ // vertex is alive, insert it into all the
71
+ // alive sets on the current DFS path
72
+ // (including `vertex`).
73
+ for st in stack. iter_mut ( ) {
74
+ if let Some ( ref mut st) = st. 1 {
75
+ st. insert ( * vertex) ;
76
+ }
77
+ }
46
78
stack. truncate ( elt_index) ;
47
79
break ;
48
80
}
49
81
}
50
82
} else {
51
- stack. push ( * v )
83
+ stack. push ( ( * v , None ) )
52
84
}
53
85
}
54
86
}
55
- Ok ( alive )
87
+ unreachable ! ( )
56
88
}
57
89
58
- pub fn find_alive_up < T : GraphTxnT > (
90
+ pub fn find_alive_up < ' a , T : GraphTxnT > (
59
91
txn : & T ,
60
92
channel : & T :: Graph ,
61
93
files : & mut HashSet < Vertex < ChangeId > > ,
62
94
vertex0 : Vertex < ChangeId > ,
63
95
change : ChangeId ,
64
- cache : & mut HashMap < Vertex < ChangeId > , ( Alive , Alive ) > ,
65
- ) -> Result < Alive , BlockError < T :: GraphError > > {
96
+ cache : & ' a mut HashMap <
97
+ Vertex < ChangeId > ,
98
+ ( Option < HashSet < Vertex < ChangeId > > > , HashSet < Vertex < ChangeId > > ) ,
99
+ > ,
100
+ ) -> Result < & ' a Option < HashSet < Vertex < ChangeId > > > , BlockError < T :: GraphError > > {
66
101
debug ! ( "find alive up: {:?}" , vertex0) ;
67
- let alive = Rc :: new ( RefCell :: new ( HashSet :: default ( ) ) ) ;
68
- let files_ = Rc :: new ( RefCell :: new ( HashSet :: default ( ) ) ) ;
69
- let mut stack = vec ! [ SerializedEdge :: empty( vertex0. end_pos( ) , ChangeId :: ROOT ) ] ;
102
+ let mut stack: Vec < (
103
+ _ ,
104
+ Option < ( HashSet < Vertex < ChangeId > > , HashSet < Vertex < ChangeId > > ) > ,
105
+ ) > = vec ! [ (
106
+ SerializedEdge :: empty( vertex0. end_pos( ) , ChangeId :: ROOT ) ,
107
+ None ,
108
+ ) ] ;
70
109
let mut visited = HashSet :: default ( ) ;
71
110
72
- while let Some ( elt) = stack. pop ( ) {
111
+ while let Some ( ( elt, alive ) ) = stack. pop ( ) {
73
112
if elt. dest ( ) . is_root ( ) {
74
113
continue ;
75
114
}
76
- if !visited. insert ( elt. dest ( ) ) {
115
+ if let Some ( ( alive, files_) ) = alive {
116
+ let vertex = * txn. find_block_end ( & channel, elt. dest ( ) ) ?;
117
+ cache. insert ( vertex, ( Some ( alive) , files_) ) ;
118
+ if stack. is_empty ( ) {
119
+ // Done!
120
+ return Ok ( & cache. get ( & vertex0) . unwrap ( ) . 0 ) ;
121
+ }
77
122
continue ;
78
- }
79
- let vertex = * txn. find_block_end ( & channel, elt. dest ( ) ) ?;
80
- debug ! ( "vertex = {:?}" , vertex) ;
81
- let is_cached = if let Some ( ( c, f) ) = cache. get ( & vertex) {
82
- alive. borrow_mut ( ) . extend ( c. borrow ( ) . iter ( ) . cloned ( ) ) ;
83
- files_. borrow_mut ( ) . extend ( f. borrow ( ) . iter ( ) . cloned ( ) ) ;
84
- files. extend ( f. borrow ( ) . iter ( ) . cloned ( ) ) ;
85
- // We're not continuing here, since the while loop below
86
- // needs to insert stuff into `files` and `files_`.
87
- true
88
123
} else {
89
- cache. insert ( vertex, ( alive. clone ( ) , files_. clone ( ) ) ) ;
90
- false
124
+ if !visited. insert ( elt. dest ( ) ) {
125
+ continue ;
126
+ }
127
+ stack. push ( ( elt, Some ( ( HashSet :: new ( ) , HashSet :: new ( ) ) ) ) ) ;
91
128
} ;
129
+ let vertex = * txn. find_block_end ( & channel, elt. dest ( ) ) ?;
130
+ debug ! ( "vertex = {:?}" , vertex) ;
131
+ if let Some ( ( c, d) ) = cache. get ( & vertex) {
132
+ debug ! ( "Cached: {:?} {:?}" , c, d) ;
133
+ for st in stack. iter_mut ( ) {
134
+ if let Some ( ( ref mut al, ref mut f) ) = st. 1 {
135
+ if let Some ( c) = c {
136
+ al. extend ( c. iter ( ) . cloned ( ) ) ;
137
+ } else {
138
+ al. insert ( vertex) ;
139
+ }
140
+ f. extend ( d. iter ( ) . cloned ( ) ) ;
141
+ files. extend ( d. iter ( ) . cloned ( ) ) ;
142
+ }
143
+ }
144
+ continue ;
145
+ }
92
146
debug ! ( "find_alive_up: elt = {:?}, vertex = {:?}" , elt, vertex) ;
93
147
debug ! ( "stack = {:?}" , stack) ;
94
148
let elt_index = stack. len ( ) ;
95
- let mut is_file = false ;
149
+ let mut is_file = false ; // Is this the "inode" vertex of a file?
96
150
let mut it = iter_adj_all ( txn, & channel, vertex) ?;
97
151
while let Some ( v) = it. next ( ) {
98
152
let v = v?;
@@ -105,40 +159,59 @@ pub fn find_alive_up<T: GraphTxnT>(
105
159
continue ;
106
160
}
107
161
if !v. flag ( ) . is_deleted ( ) {
162
+ if vertex == vertex0 {
163
+ // vertex0 is alive.
164
+ stack. truncate ( elt_index) ;
165
+ let ( _, alive) = stack. pop ( ) . unwrap ( ) ;
166
+ let ( alive, _) = alive. unwrap ( ) ;
167
+ assert ! ( alive. is_empty( ) ) ;
168
+ cache. insert ( vertex0, ( None , HashSet :: new ( ) ) ) ;
169
+ return Ok ( & cache. get ( & vertex0) . unwrap ( ) . 0 ) ;
170
+ }
108
171
if v. flag ( ) . is_folder ( ) {
109
172
for e in it {
110
173
let e = e?;
111
174
is_file |= !e. flag ( ) . intersects ( EdgeFlags :: parent_folder ( ) )
112
175
}
113
- if is_file && vertex != vertex0 {
176
+ if is_file {
114
177
debug ! ( "is alive + is file {:?}" , vertex) ;
115
- alive. borrow_mut ( ) . insert ( vertex) ;
116
- files_. borrow_mut ( ) . insert ( vertex) ;
178
+ for st in stack. iter_mut ( ) {
179
+ if let Some ( ( ref mut al, ref mut fi) ) = st. 1 {
180
+ al. insert ( vertex) ;
181
+ fi. insert ( vertex) ;
182
+ }
183
+ }
117
184
files. insert ( vertex) ;
118
185
}
119
186
break ;
120
187
} else if v. flag ( ) . is_block ( ) || vertex. is_empty ( ) {
121
- if vertex != vertex0 {
122
- debug ! ( "is alive {:?}" , vertex) ;
123
- alive. borrow_mut ( ) . insert ( vertex) ;
188
+ debug ! ( "is alive {:?}" , vertex) ;
189
+ for st in stack. iter_mut ( ) {
190
+ if let Some ( ( ref mut st, _) ) = st. 1 {
191
+ st. insert ( vertex) ;
192
+ }
124
193
}
125
194
stack. truncate ( elt_index) ;
126
195
break ;
127
196
}
128
197
}
129
198
if v. flag ( ) . is_folder ( ) {
130
- if is_file && vertex != vertex0 {
131
- debug ! ( "is alive {:?}" , vertex) ;
132
- alive. borrow_mut ( ) . insert ( vertex) ;
133
- files_. borrow_mut ( ) . insert ( vertex) ;
199
+ if is_file {
200
+ debug ! ( "is pseudo-alive folder {:?}" , vertex) ;
201
+ for st in stack. iter_mut ( ) {
202
+ if let Some ( ( ref mut al, ref mut fi) ) = st. 1 {
203
+ al. insert ( vertex) ;
204
+ fi. insert ( vertex) ;
205
+ }
206
+ }
134
207
files. insert ( vertex) ;
135
208
}
136
209
break ;
137
- } else if !is_cached {
138
- stack. push ( * v )
210
+ } else {
211
+ stack. push ( ( * v , None ) )
139
212
}
140
213
}
141
214
debug ! ( "is_file = {:?}" , is_file) ;
142
215
}
143
- Ok ( alive )
216
+ unreachable ! ( )
144
217
}
0 commit comments