@@ -2,41 +2,29 @@ use std::cmp::Ordering;
2
2
3
3
use super :: {
4
4
balance_queue:: BalanceQueue ,
5
- followers:: {
6
- add_follower_count, remove_follower_count, remove_positive_follower_count,
7
- RemovePositveFollowerCountResult ,
8
- } ,
9
- in_progress:: is_in_progress,
5
+ in_progress:: { is_in_progress, start_in_progress_all, start_in_progress_count} ,
10
6
increase:: IncreaseReason ,
11
7
increase_aggregation_number_internal,
12
- uppers:: {
13
- add_upper_count, remove_positive_upper_count, remove_upper_count,
14
- RemovePositiveUpperCountResult ,
15
- } ,
16
- AggregationContext , AggregationNode ,
8
+ notify_lost_follower:: notify_lost_follower,
9
+ notify_new_follower:: notify_new_follower,
10
+ util:: { get_aggregated_add_change, get_aggregated_remove_change, get_followers_or_children} ,
11
+ AggregationContext , AggregationNode , PreparedInternalOperation , PreparedOperation , StackVec ,
17
12
} ;
18
13
19
- // Migrated followers to uppers or uppers to followers depending on the
14
+ // Migrate followers to uppers or uppers to followers depending on the
20
15
// aggregation numbers of the nodes involved in the edge. Might increase targets
21
16
// aggregation number if they are equal.
22
17
pub ( super ) fn balance_edge < C : AggregationContext > (
23
18
ctx : & C ,
24
19
balance_queue : & mut BalanceQueue < C :: NodeRef > ,
25
20
upper_id : & C :: NodeRef ,
26
- mut upper_aggregation_number : u32 ,
27
21
target_id : & C :: NodeRef ,
28
- mut target_aggregation_number : u32 ,
29
- ) -> ( u32 , u32 ) {
30
- // too many uppers on target
31
- let mut extra_uppers = 0 ;
32
- // too many followers on upper
33
- let mut extra_followers = 0 ;
34
- // The last info about uppers
35
- let mut uppers_count: Option < isize > = None ;
36
- // The last info about followers
37
- let mut followers_count = None ;
38
-
22
+ ) {
39
23
loop {
24
+ let ( mut upper, mut target) = ctx. node_pair ( upper_id, target_id) ;
25
+ let upper_aggregation_number = upper. aggregation_number ( ) ;
26
+ let target_aggregation_number = target. aggregation_number ( ) ;
27
+
40
28
let root = upper_aggregation_number == u32:: MAX || target_aggregation_number == u32:: MAX ;
41
29
let order = if root {
42
30
Ordering :: Greater
@@ -45,164 +33,158 @@ pub(super) fn balance_edge<C: AggregationContext>(
45
33
} ;
46
34
match order {
47
35
Ordering :: Equal => {
48
- // we probably want to increase the aggregation number of target
49
- let upper = ctx. node ( upper_id) ;
50
- upper_aggregation_number = upper. aggregation_number ( ) ;
51
36
drop ( upper) ;
52
- if upper_aggregation_number != u32:: MAX
53
- && upper_aggregation_number == target_aggregation_number
54
- {
55
- let target = ctx. node ( target_id) ;
56
- target_aggregation_number = target. aggregation_number ( ) ;
57
- if upper_aggregation_number == target_aggregation_number {
58
- // increase target aggregation number
59
- increase_aggregation_number_internal (
60
- ctx,
61
- balance_queue,
62
- target,
63
- target_id,
64
- target_aggregation_number + 1 ,
65
- target_aggregation_number + 1 ,
66
- IncreaseReason :: EqualAggregationNumberOnBalance ,
67
- ) ;
68
- }
69
- }
37
+ // increase target aggregation number
38
+ increase_aggregation_number_internal (
39
+ ctx,
40
+ balance_queue,
41
+ target,
42
+ target_id,
43
+ target_aggregation_number + 1 ,
44
+ target_aggregation_number + 1 ,
45
+ IncreaseReason :: EqualAggregationNumberOnBalance ,
46
+ ) ;
70
47
}
71
48
Ordering :: Less => {
72
- // target should probably be a follower of upper
73
- if uppers_count. map_or ( false , |count| count <= 0 ) {
74
- // We already removed all uppers, maybe too many
49
+ if is_in_progress ( ctx, upper_id) {
50
+ drop ( target) ;
51
+ let AggregationNode :: Aggegating ( aggregating) = & mut * upper else {
52
+ unreachable ! ( ) ;
53
+ } ;
54
+ aggregating
55
+ . enqueued_balancing
56
+ . push ( ( upper_id. clone ( ) , target_id. clone ( ) ) ) ;
57
+ drop ( upper) ;
58
+ // Somebody else will balance this edge
75
59
break ;
76
- } else if extra_followers == 0 {
77
- let upper = ctx. node ( upper_id) ;
78
- upper_aggregation_number = upper. aggregation_number ( ) ;
79
- if upper_aggregation_number < target_aggregation_number {
80
- // target should be a follower of upper
81
- // add some extra followers
82
- let count = uppers_count. unwrap_or ( 1 ) as usize ;
83
- extra_followers += count;
84
- followers_count = Some ( add_follower_count (
85
- ctx,
86
- balance_queue,
87
- upper,
88
- upper_id,
89
- target_id,
90
- count,
91
- true ,
92
- ) ) ;
93
- }
60
+ }
61
+
62
+ // target should be a follower of upper
63
+ let count = target
64
+ . uppers_mut ( )
65
+ . remove_all_positive_clonable_count ( upper_id) ;
66
+ if count == 0 {
67
+ break ;
68
+ }
69
+ let added = upper
70
+ . followers_mut ( )
71
+ . unwrap ( )
72
+ . add_clonable_count ( target_id, count) ;
73
+
74
+ // target removed as upper
75
+ let remove_change = get_aggregated_remove_change ( ctx, & target) ;
76
+ let followers = get_followers_or_children ( ctx, & target) ;
77
+
78
+ let upper_uppers = if added {
79
+ // target added as follower
80
+ let uppers = upper. uppers ( ) . iter ( ) . cloned ( ) . collect :: < StackVec < _ > > ( ) ;
81
+ start_in_progress_all ( ctx, & uppers) ;
82
+ uppers
94
83
} else {
95
- // we already have extra followers, remove some uppers to balance
96
- let count = extra_followers + extra_uppers;
97
- let target = ctx. node ( target_id) ;
98
- if is_in_progress ( ctx, upper_id) {
99
- drop ( target) ;
100
- let mut upper = ctx. node ( upper_id) ;
101
- if is_in_progress ( ctx, upper_id) {
102
- let AggregationNode :: Aggegating ( aggregating) = & mut * upper else {
103
- unreachable ! ( ) ;
104
- } ;
105
- aggregating. enqueued_balancing . push ( (
106
- upper_id. clone ( ) ,
107
- upper_aggregation_number,
108
- target_id. clone ( ) ,
109
- target_aggregation_number,
110
- ) ) ;
111
- drop ( upper) ;
112
- // Somebody else will balance this edge
113
- return ( upper_aggregation_number, target_aggregation_number) ;
114
- }
115
- } else {
116
- let RemovePositiveUpperCountResult {
117
- removed_count,
118
- remaining_count,
119
- } = remove_positive_upper_count (
120
- ctx,
121
- balance_queue,
122
- target,
123
- upper_id,
124
- count,
125
- ) ;
126
- decrease_numbers ( removed_count, & mut extra_uppers, & mut extra_followers) ;
127
- uppers_count = Some ( remaining_count) ;
128
- }
84
+ Default :: default ( )
85
+ } ;
86
+
87
+ drop ( target) ;
88
+
89
+ // target removed as upper
90
+ let remove_prepared =
91
+ remove_change. and_then ( |remove_change| upper. apply_change ( ctx, remove_change) ) ;
92
+ start_in_progress_count ( ctx, upper_id, followers. len ( ) as u32 ) ;
93
+ let prepared = followers
94
+ . into_iter ( )
95
+ . map ( |child_id| {
96
+ upper. notify_lost_follower ( ctx, balance_queue, upper_id, & child_id)
97
+ } )
98
+ . collect :: < StackVec < _ > > ( ) ;
99
+ drop ( upper) ;
100
+
101
+ // target added as follower
102
+ for upper_id in upper_uppers {
103
+ notify_new_follower (
104
+ ctx,
105
+ balance_queue,
106
+ ctx. node ( & upper_id) ,
107
+ & upper_id,
108
+ target_id,
109
+ false ,
110
+ ) ;
129
111
}
112
+
113
+ // target removed as upper
114
+ remove_prepared. apply ( ctx) ;
115
+ prepared. apply ( ctx, balance_queue) ;
116
+
117
+ break ;
130
118
}
131
119
Ordering :: Greater => {
132
- // target should probably be an inner node of upper
133
- if followers_count. map_or ( false , |count| count <= 0 ) {
134
- // We already removed all followers, maybe too many
120
+ if is_in_progress ( ctx, upper_id) {
121
+ let AggregationNode :: Aggegating ( aggregating) = & mut * upper else {
122
+ unreachable ! ( ) ;
123
+ } ;
124
+ aggregating
125
+ . enqueued_balancing
126
+ . push ( ( upper_id. clone ( ) , target_id. clone ( ) ) ) ;
127
+ drop ( upper) ;
128
+ // Somebody else will balance this edge
129
+ break ;
130
+ }
131
+
132
+ // target should be a inner node of upper
133
+ let count = upper
134
+ . followers_mut ( )
135
+ . unwrap ( )
136
+ . remove_all_positive_clonable_count ( target_id) ;
137
+ if count == 0 {
135
138
break ;
136
- } else if extra_uppers == 0 {
137
- let target = ctx. node ( target_id) ;
138
- target_aggregation_number = target. aggregation_number ( ) ;
139
- if root || target_aggregation_number < upper_aggregation_number {
140
- // target should be a inner node of upper
141
- if is_in_progress ( ctx, upper_id) {
142
- drop ( target) ;
143
- let mut upper = ctx. node ( upper_id) ;
144
- if is_in_progress ( ctx, upper_id) {
145
- let AggregationNode :: Aggegating ( aggregating) = & mut * upper else {
146
- unreachable ! ( ) ;
147
- } ;
148
- aggregating. enqueued_balancing . push ( (
149
- upper_id. clone ( ) ,
150
- upper_aggregation_number,
151
- target_id. clone ( ) ,
152
- target_aggregation_number,
153
- ) ) ;
154
- drop ( upper) ;
155
- // Somebody else will balance this edge
156
- return ( upper_aggregation_number, target_aggregation_number) ;
157
- }
158
- } else {
159
- // add some extra uppers
160
- let count = followers_count. unwrap_or ( 1 ) as usize ;
161
- extra_uppers += count;
162
- uppers_count = Some (
163
- add_upper_count (
164
- ctx,
165
- balance_queue,
166
- target,
167
- target_id,
168
- upper_id,
169
- count,
170
- true ,
171
- )
172
- . new_count ,
173
- ) ;
174
- }
175
- }
139
+ }
140
+ let added = target. uppers_mut ( ) . add_clonable_count ( upper_id, count) ;
141
+
142
+ // target removed as follower
143
+ let uppers = upper. uppers ( ) . iter ( ) . cloned ( ) . collect :: < StackVec < _ > > ( ) ;
144
+ start_in_progress_all ( ctx, & uppers) ;
145
+
146
+ let ( add_change, followers) = if added {
147
+ // target added as upper
148
+ let add_change = get_aggregated_add_change ( ctx, & target) ;
149
+ let followers = get_followers_or_children ( ctx, & target) ;
150
+ start_in_progress_count ( ctx, upper_id, followers. len ( ) as u32 ) ;
151
+ ( add_change, followers)
176
152
} else {
177
- // we already have extra uppers, try to remove some followers to balance
178
- let count = extra_followers + extra_uppers;
179
- let upper = ctx. node ( upper_id) ;
180
- let RemovePositveFollowerCountResult {
181
- removed_count,
182
- remaining_count,
183
- } = remove_positive_follower_count ( ctx, balance_queue, upper, target_id, count) ;
184
- decrease_numbers ( removed_count, & mut extra_followers, & mut extra_uppers) ;
185
- followers_count = Some ( remaining_count) ;
153
+ ( None , Default :: default ( ) )
154
+ } ;
155
+
156
+ drop ( target) ;
157
+
158
+ // target added as upper
159
+ let add_prepared =
160
+ add_change. and_then ( |add_change| upper. apply_change ( ctx, add_change) ) ;
161
+ let prepared = followers
162
+ . into_iter ( )
163
+ . filter_map ( |child_id| {
164
+ upper. notify_new_follower ( ctx, balance_queue, upper_id, & child_id, false )
165
+ } )
166
+ . collect :: < StackVec < _ > > ( ) ;
167
+
168
+ drop ( upper) ;
169
+
170
+ add_prepared. apply ( ctx) ;
171
+ for prepared in prepared {
172
+ prepared. apply ( ctx, balance_queue) ;
186
173
}
174
+
175
+ // target removed as follower
176
+ for upper_id in uppers {
177
+ notify_lost_follower (
178
+ ctx,
179
+ balance_queue,
180
+ ctx. node ( & upper_id) ,
181
+ & upper_id,
182
+ target_id,
183
+ ) ;
184
+ }
185
+
186
+ break ;
187
187
}
188
188
}
189
189
}
190
- if extra_followers > 0 {
191
- let upper = ctx. node ( upper_id) ;
192
- remove_follower_count ( ctx, balance_queue, upper, target_id, extra_followers) ;
193
- }
194
- if extra_uppers > 0 {
195
- let target = ctx. node ( target_id) ;
196
- remove_upper_count ( ctx, balance_queue, target, upper_id, extra_uppers) ;
197
- }
198
- ( upper_aggregation_number, target_aggregation_number)
199
- }
200
-
201
- fn decrease_numbers ( amount : usize , a : & mut usize , b : & mut usize ) {
202
- if * a >= amount {
203
- * a -= amount;
204
- } else {
205
- * b -= amount - * a;
206
- * a = 0 ;
207
- }
208
190
}
0 commit comments