@@ -105,53 +105,54 @@ protected void killCounterLeft(ExistsCounter<LeftTuple_> counter) {
105105 }
106106 }
107107
108- protected void incrementCounterRightWithoutIndictment (ExistsCounter <LeftTuple_ > counter ) {
108+ protected void incrementCounterRight (ExistsCounter <LeftTuple_ > counter ) {
109109 if (counter .countRight == 0 ) {
110110 if (shouldExist ) {
111111 doInsertCounter (counter );
112112 } else {
113113 doRetractCounter (counter );
114114 }
115115 } // Else do not even propagate an update
116- // NOTE: By not propagating here, the left tuple's indicted objects can be stale
117- // if an element is removed.
118116 counter .countRight ++;
119117 }
120118
121119 protected void incrementCounterRightUpdatingIndictment (ExistsCounter <LeftTuple_ > counter , UniTuple <Right_ > rightTuple ) {
120+ IndictmentSource .addSupport (getId (), counter .getTuple (), rightTuple );
122121 if (counter .countRight == 0 ) {
123122 if (shouldExist ) {
124123 doInsertCounter (counter );
125124 } else {
126125 doRetractCounter (counter );
127126 }
128- } else {
129- // count != 0, so only propagate if we are in an `ifExists`
130- if (shouldExist ) {
131- doUpdateCounter (counter );
132- }
133- } // Else do not even propagate an update
134- // NOTE: By not propagating here, the left tuple's indicted objects can be stale
135- // if an element is removed.
136- IndictmentSource .addSupport (getId (), counter .leftTuple , rightTuple );
127+ } else if (shouldExist ) {
128+ doUpdateCounter (counter );
129+ }
137130 counter .countRight ++;
138131 }
139132
140133 protected void decrementCounterRight (ExistsCounter <LeftTuple_ > counter ) {
141134 counter .countRight --;
142- IndictmentSource .removeSupport (getId (), counter .leftTuple , rightTuple );
143135 if (counter .countRight == 0 ) {
144136 if (shouldExist ) {
145137 doRetractCounter (counter );
146138 } else {
147139 doInsertCounter (counter );
148140 }
149- } else {
150- // count != 0, so only propagate if we are in an `ifExists`
141+ } // Else do not even propagate an update
142+ }
143+
144+ protected void decrementCounterRightUpdatingIndictment (ExistsCounter <LeftTuple_ > counter , UniTuple <Right_ > rightTuple ) {
145+ IndictmentSource .removeSupport (getId (), counter .getTuple (), rightTuple );
146+ counter .countRight --;
147+ if (counter .countRight == 0 ) {
151148 if (shouldExist ) {
152- doUpdateCounter (counter );
149+ doRetractCounter (counter );
150+ } else {
151+ doInsertCounter (counter );
153152 }
154- } // Else do not even propagate an update
153+ } else if (shouldExist ) {
154+ doUpdateCounter (counter );
155+ }
155156 }
156157
157158 // Clears the left tracker list rooted at leftTuple's inputStoreIndexLeftTrackerList slot,
@@ -192,18 +193,18 @@ private void removeRight(FilteringTracker<LeftTuple_> tracker) {
192193 // Walk safety: removeFromLeft only touches left-side links, so rightNext is stable across the call.
193194 protected void clearRightTrackerList (UniTuple <Right_ > rightTuple ) {
194195 FilteringTracker <LeftTuple_ > tracker = rightTuple .removeStore (inputStoreIndexRightTrackerList );
195- if (rightTuple .getIndictmentSource () ! = IndictmentSource .DISABLED ) {
196+ if (rightTuple .getIndictmentSource () = = IndictmentSource .DISABLED ) {
196197 while (tracker != null ) {
197198 var next = tracker .rightNext ;
198- decrementCounterRightUpdatingIndictment (tracker .counter , rightTuple );
199- removeFromLeft (tracker );
199+ decrementCounterRight (tracker .counter );
200+ removeLeft (tracker );
200201 tracker = next ;
201202 }
202203 } else {
203204 while (tracker != null ) {
204205 var next = tracker .rightNext ;
205- decrementCounterRightWithoutIndictment (tracker .counter );
206- removeFromLeft (tracker );
206+ decrementCounterRightUpdatingIndictment (tracker .counter , rightTuple );
207+ removeLeft (tracker );
207208 tracker = next ;
208209 }
209210 }
@@ -233,13 +234,17 @@ protected void updateCounterLeft(ExistsCounter<LeftTuple_> counter, UniTuple<Rig
233234 // which happens when the right input's node sits in a higher layer than the left input's,
234235 // so the left's inserts and updates are delivered before the right's retracts are.
235236 // Skipping is safe, as the pending retract will not have a tracker to clear for this pair.
237+ IndictmentSource .removeSupport (getId (), counter .getTuple (), rightTuple );
236238 return ;
237239 }
238240 if (testFiltering (counter .leftTuple , rightTuple )) {
239241 counter .countRight ++;
242+ IndictmentSource .addSupport (getId (), counter .getTuple (), rightTuple );
240243 var tracker = new FilteringTracker <>(counter , rightTuple );
241244 linkLeft (tracker );
242245 linkRight (tracker );
246+ } else {
247+ IndictmentSource .removeSupport (getId (), counter .getTuple (), rightTuple );
243248 }
244249 }
245250
@@ -284,13 +289,17 @@ protected void updateCounterRight(ExistsCounter<LeftTuple_> counter, UniTuple<Ri
284289 // The left tuple can be inactive here because its node sits in a higher layer than the right's:
285290 // the right's inserts and updates are delivered before the left's retracts are.
286291 // The mirror case is possible too, see updateCounterLeft(...).
292+ IndictmentSource .removeSupport (getId (), counter .getTuple (), rightTuple );
287293 return ;
288294 }
289295 if (testFiltering (leftTuple , rightTuple )) {
290- incrementCounterRightUpdatingIndictment (counter , rightTuple );
296+ incrementCounterRight (counter );
297+ IndictmentSource .addSupport (getId (), counter .getTuple (), rightTuple );
291298 var tracker = new FilteringTracker <>(counter , rightTuple );
292299 linkLeft (tracker );
293300 linkRight (tracker );
301+ } else {
302+ IndictmentSource .removeSupport (getId (), counter .getTuple (), rightTuple );
294303 }
295304 }
296305
@@ -303,6 +312,21 @@ private void doInsertCounter(ExistsCounter<LeftTuple_> counter) {
303312 }
304313 }
305314
315+ private void doUpdateCounter (ExistsCounter <LeftTuple_ > counter ) {
316+ switch (counter .state ) {
317+ case CREATING , UPDATING -> {
318+ // Do nothing
319+ }
320+ case OK -> {
321+ propagationQueue .update (counter );
322+ }
323+ case DYING , DEAD , ABORTING -> {
324+ throw new IllegalStateException ("Impossible state: The counter (%s) has an impossible retract state (%s)."
325+ .formatted (counter , counter .state ));
326+ }
327+ }
328+ }
329+
306330 private void doRetractCounter (ExistsCounter <LeftTuple_ > counter ) {
307331 switch (counter .state ) {
308332 case CREATING -> // Kill it before it propagates.
@@ -315,15 +339,6 @@ private void doRetractCounter(ExistsCounter<LeftTuple_> counter) {
315339 }
316340 }
317341
318- private void doUpdateCounter (ExistsCounter <LeftTuple_ > counter ) {
319- switch (counter .state ) {
320- case DYING , OK , UPDATING , CREATING -> propagationQueue .update (counter );
321- case DEAD , ABORTING -> propagationQueue .insert (counter );
322- default -> throw new IllegalStateException ("Impossible state: the counter (%s) has an impossible insert state (%s)."
323- .formatted (counter , counter .state ));
324- }
325- }
326-
327342 @ Override
328343 protected boolean canProduceTuples () {
329344 // The left input must produce tuples no matter what,
@@ -369,4 +384,4 @@ protected static final class FilteringTracker<LeftTuple_ extends Tuple> {
369384
370385 }
371386
372- }
387+ }
0 commit comments