@@ -97,7 +97,7 @@ private static final class UnderlyingTableMaintainer extends ReferenceCountedLiv
9797 @ SuppressWarnings ("FieldCanBeLocal" ) // We need to hold onto this reference for reachability purposes.
9898 private final Runnable processNewLocationsUpdateRoot ;
9999
100- private final UpdateCommitter <UnderlyingTableMaintainer > removedLocationsComitter ;
100+ private final UpdateCommitter <UnderlyingTableMaintainer > removedLocationsCommitter ;
101101 private List <Table > removedConstituents = null ;
102102
103103 private UnderlyingTableMaintainer (
@@ -156,12 +156,12 @@ protected void instrumentedRefresh() {
156156 };
157157 refreshCombiner .addSource (processNewLocationsUpdateRoot );
158158
159- this .removedLocationsComitter = new UpdateCommitter <>(
159+ this .removedLocationsCommitter = new UpdateCommitter <>(
160160 this ,
161161 result .getUpdateGraph (),
162162 ignored -> {
163163 Assert .neqNull (removedConstituents , "removedConstituents" );
164- removedConstituents .forEach ( result :: unmanage );
164+ result . unmanage ( removedConstituents .stream () );
165165 removedConstituents = null ;
166166 });
167167 processPendingLocations (false );
@@ -170,7 +170,7 @@ protected void instrumentedRefresh() {
170170 pendingLocationStates = null ;
171171 readyLocationStates = null ;
172172 processNewLocationsUpdateRoot = null ;
173- removedLocationsComitter = null ;
173+ removedLocationsCommitter = null ;
174174 tableLocationProvider .refresh ();
175175
176176 final Collection <TableLocation > locations = new ArrayList <>();
@@ -203,7 +203,8 @@ private QueryTable result() {
203203 private RowSet sortAndAddLocations (@ NotNull final Stream <TableLocation > locations ) {
204204 final long initialLastRowKey = resultRows .lastRowKey ();
205205 final MutableLong lastInsertedRowKey = new MutableLong (initialLastRowKey );
206- locations .sorted (Comparator .comparing (TableLocation ::getKey )).forEach (tl -> {
206+ // Note that makeConstituentTable expects us to subsequently unmanage the TableLocations
207+ unmanage (locations .sorted (Comparator .comparing (TableLocation ::getKey )).peek (tl -> {
207208 final long constituentRowKey = lastInsertedRowKey .incrementAndGet ();
208209 final Table constituentTable = makeConstituentTable (tl );
209210
@@ -216,7 +217,7 @@ private RowSet sortAndAddLocations(@NotNull final Stream<TableLocation> location
216217 if (result .isRefreshing ()) {
217218 result .manage (constituentTable );
218219 }
219- });
220+ })) ;
220221 return initialLastRowKey == lastInsertedRowKey .get ()
221222 ? RowSetFactory .empty ()
222223 : RowSetFactory .fromRange (initialLastRowKey + 1 , lastInsertedRowKey .get ());
@@ -235,7 +236,7 @@ private Table makeConstituentTable(@NotNull final TableLocation tableLocation) {
235236 // Transfer management to the constituent CSM. NOTE: this is likely to end up double-managed
236237 // after the CSM adds the location to the table, but that's acceptable.
237238 constituent .columnSourceManager .manage (tableLocation );
238- unmanage ( tableLocation );
239+ // Note that the caller is now responsible for unmanaging tableLocation on behalf of this.
239240
240241 // Be careful to propagate the systemic attribute properly to child tables
241242 constituent .setAttribute (Table .SYSTEMIC_TABLE_ATTRIBUTE , result .isSystemicObject ());
@@ -293,8 +294,12 @@ private RowSet processAdditions(final TableLocationSubscriptionBuffer.LocationUp
293294 readyLocationStates .offer (pendingLocationState );
294295 }
295296 }
296- final RowSet added = sortAndAddLocations (readyLocationStates .stream ()
297- .map (PendingLocationState ::release ));
297+
298+ if (readyLocationStates .isEmpty ()) {
299+ return RowSetFactory .empty ();
300+ }
301+
302+ final RowSet added = sortAndAddLocations (readyLocationStates .stream ().map (PendingLocationState ::release ));
298303 readyLocationStates .clearFast ();
299304 return added ;
300305 }
@@ -312,14 +317,23 @@ private RowSet processRemovals(final TableLocationSubscriptionBuffer.LocationUpd
312317 }
313318
314319 // Iterate through the pending locations and remove any that are in the removed set.
320+ List <LivenessReferent > toUnmanage = null ;
315321 for (final Iterator <PendingLocationState > iter = pendingLocationStates .iterator (); iter .hasNext ();) {
316322 final PendingLocationState pendingLocationState = iter .next ();
317323 if (relevantRemovedLocations .contains (pendingLocationState .location .getKey ())) {
318324 iter .remove ();
319- // Release the state and unmanage the location
320- unmanage (pendingLocationState .release ());
325+ // Release the state and plan to unmanage the location
326+ if (toUnmanage == null ) {
327+ toUnmanage = new ArrayList <>();
328+ }
329+ toUnmanage .add (pendingLocationState .release ());
321330 }
322331 }
332+ if (toUnmanage != null ) {
333+ unmanage (toUnmanage .stream ());
334+ // noinspection UnusedAssignment
335+ toUnmanage = null ;
336+ }
323337
324338 // At the end of the cycle we need to make sure we unmanage any removed constituents.
325339 this .removedConstituents = new ArrayList <>(relevantRemovedLocations .size ());
@@ -350,7 +364,7 @@ private RowSet processRemovals(final TableLocationSubscriptionBuffer.LocationUpd
350364 removedConstituents = null ;
351365 return RowSetFactory .empty ();
352366 }
353- this .removedLocationsComitter .maybeActivate ();
367+ this .removedLocationsCommitter .maybeActivate ();
354368
355369 final WritableRowSet deletedRows = deleteBuilder .build ();
356370 resultTableLocationKeys .setNull (deletedRows );
0 commit comments