28
28
import io .deephaven .configuration .Configuration ;
29
29
import io .deephaven .datastructures .util .CollectionUtil ;
30
30
import io .deephaven .engine .context .ExecutionContext ;
31
+ import io .deephaven .engine .table .impl .util .*;
31
32
import io .deephaven .engine .updategraph .UpdateGraph ;
32
33
import io .deephaven .engine .exceptions .CancellationException ;
33
34
import io .deephaven .engine .liveness .LivenessScope ;
48
49
import io .deephaven .engine .table .impl .select .MatchPairFactory ;
49
50
import io .deephaven .engine .table .impl .select .SelectColumnFactory ;
50
51
import io .deephaven .engine .table .impl .updateby .UpdateBy ;
51
- import io .deephaven .engine .table .impl .util .ImmediateJobScheduler ;
52
- import io .deephaven .engine .table .impl .util .JobScheduler ;
53
- import io .deephaven .engine .table .impl .util .OperationInitializerJobScheduler ;
54
52
import io .deephaven .engine .table .impl .select .analyzers .SelectAndViewAnalyzerWrapper ;
55
- import io .deephaven .engine .table .impl .util .FieldUtils ;
56
53
import io .deephaven .engine .table .impl .sources .ring .RingTableTools ;
57
54
import io .deephaven .engine .table .iterators .*;
58
55
import io .deephaven .engine .updategraph .DynamicNode ;
59
56
import io .deephaven .engine .util .*;
60
57
import io .deephaven .engine .util .systemicmarking .SystemicObject ;
61
58
import io .deephaven .util .annotations .InternalUseOnly ;
59
+ import io .deephaven .util .annotations .ReferentialIntegrity ;
62
60
import io .deephaven .vector .Vector ;
63
61
import io .deephaven .engine .table .impl .perf .QueryPerformanceRecorder ;
64
62
import io .deephaven .engine .util .systemicmarking .SystemicObjectTracker ;
@@ -982,6 +980,9 @@ public static class FilteredTable extends QueryTable implements WhereFilter.Reco
982
980
private boolean refilterUnmatchedRequested = false ;
983
981
private MergedListener whereListener ;
984
982
983
+ @ ReferentialIntegrity
984
+ Runnable delayedErrorReference ;
985
+
985
986
public FilteredTable (final TrackingRowSet currentMapping , final QueryTable source ) {
986
987
super (source .getDefinition (), currentMapping , source .columns , null , null );
987
988
this .source = source ;
@@ -1066,9 +1067,10 @@ void doRefilter(
1066
1067
1067
1068
if (refilterMatchedRequested && refilterUnmatchedRequested ) {
1068
1069
final WhereListener .ListenerFilterExecution filterExecution =
1069
- listener .makeFilterExecution (source .getRowSet ().copy ());
1070
+ listener .makeRefilterExecution (source .getRowSet ().copy ());
1070
1071
filterExecution .scheduleCompletion (
1071
- fe -> completeRefilterUpdate (listener , upstream , update , fe .addedResult ));
1072
+ (adds , mods ) -> completeRefilterUpdate (listener , upstream , update , adds ),
1073
+ exception -> errorRefilterUpdate (listener , exception , upstream ));
1072
1074
refilterMatchedRequested = refilterUnmatchedRequested = false ;
1073
1075
} else if (refilterUnmatchedRequested ) {
1074
1076
// things that are added or removed are already reflected in source.getRowSet
@@ -1078,9 +1080,9 @@ void doRefilter(
1078
1080
unmatchedRows .insert (upstream .modified ());
1079
1081
}
1080
1082
final RowSet unmatched = unmatchedRows .copy ();
1081
- final WhereListener .ListenerFilterExecution filterExecution = listener .makeFilterExecution (unmatched );
1082
- filterExecution .scheduleCompletion (fe -> {
1083
- final WritableRowSet newMapping = fe . addedResult ;
1083
+ final WhereListener .ListenerFilterExecution filterExecution = listener .makeRefilterExecution (unmatched );
1084
+ filterExecution .scheduleCompletion (( adds , mods ) -> {
1085
+ final WritableRowSet newMapping = adds . writableCast () ;
1084
1086
// add back what we previously matched, but for modifications and removals
1085
1087
try (final WritableRowSet previouslyMatched = getRowSet ().copy ()) {
1086
1088
if (upstream != null ) {
@@ -1089,8 +1091,8 @@ void doRefilter(
1089
1091
}
1090
1092
newMapping .insert (previouslyMatched );
1091
1093
}
1092
- completeRefilterUpdate (listener , upstream , update , fe . addedResult );
1093
- });
1094
+ completeRefilterUpdate (listener , upstream , update , adds );
1095
+ }, exception -> errorRefilterUpdate ( listener , exception , upstream ) );
1094
1096
refilterUnmatchedRequested = false ;
1095
1097
} else if (refilterMatchedRequested ) {
1096
1098
// we need to take removed rows out of our rowSet so we do not read them, and also examine added or
@@ -1103,9 +1105,10 @@ void doRefilter(
1103
1105
final RowSet matchedClone = matchedRows .copy ();
1104
1106
1105
1107
final WhereListener .ListenerFilterExecution filterExecution =
1106
- listener .makeFilterExecution (matchedClone );
1108
+ listener .makeRefilterExecution (matchedClone );
1107
1109
filterExecution .scheduleCompletion (
1108
- fe -> completeRefilterUpdate (listener , upstream , update , fe .addedResult ));
1110
+ (adds , mods ) -> completeRefilterUpdate (listener , upstream , update , adds ),
1111
+ exception -> errorRefilterUpdate (listener , exception , upstream ));
1109
1112
refilterMatchedRequested = false ;
1110
1113
} else {
1111
1114
throw new IllegalStateException ("Refilter called when a refilter was not requested!" );
@@ -1141,11 +1144,24 @@ private void completeRefilterUpdate(
1141
1144
update .shifted = upstream == null ? RowSetShiftData .EMPTY : upstream .shifted ();
1142
1145
1143
1146
notifyListeners (update );
1144
- if (upstream != null ) {
1145
- upstream .release ();
1146
- }
1147
1147
1148
- listener .setFinalExecutionStep ();
1148
+ // Release the upstream update and set the final notification step.
1149
+ listener .finalizeUpdate (upstream );
1150
+ }
1151
+
1152
+ private void errorRefilterUpdate (final WhereListener listener , final Exception e , final TableUpdate upstream ) {
1153
+ // Notify listeners that we had an issue refreshing the table.
1154
+ if (getLastNotificationStep () == updateGraph .clock ().currentStep ()) {
1155
+ if (listener != null ) {
1156
+ listener .forceReferenceCountToZero ();
1157
+ }
1158
+ delayedErrorReference = new DelayedErrorNotifier (e , listener == null ? null : listener .entry , this );
1159
+ } else {
1160
+ notifyListenersOnError (e , listener == null ? null : listener .entry );
1161
+ forceReferenceCountToZero ();
1162
+ }
1163
+ // Release the upstream update and set the final notification step.
1164
+ listener .finalizeUpdate (upstream );
1149
1165
}
1150
1166
1151
1167
private void setWhereListener (MergedListener whereListener ) {
@@ -1226,41 +1242,18 @@ private QueryTable whereInternal(final WhereFilter... filters) {
1226
1242
1227
1243
final CompletableFuture <TrackingWritableRowSet > currentMappingFuture =
1228
1244
new CompletableFuture <>();
1245
+
1229
1246
final InitialFilterExecution initialFilterExecution = new InitialFilterExecution (
1230
- this , filters , rowSetToUse .copy (), 0 , rowSetToUse .size (), null , 0 ,
1231
- usePrev ) {
1232
- @ Override
1233
- void handleUncaughtException (Exception throwable ) {
1234
- currentMappingFuture .completeExceptionally (throwable );
1235
- }
1236
- };
1237
- final ExecutionContext executionContext = ExecutionContext .getContext ();
1238
- initialFilterExecution .scheduleCompletion (x -> {
1239
- try (final SafeCloseable ignored = executionContext .open ()) {
1240
- if (x .exceptionResult != null ) {
1241
- currentMappingFuture .completeExceptionally (x .exceptionResult );
1242
- } else {
1243
- currentMappingFuture .complete (x .addedResult .toTracking ());
1244
- }
1245
- }
1246
- });
1247
+ this , filters , rowSetToUse .copy (), usePrev );
1248
+ final TrackingWritableRowSet currentMapping ;
1249
+ initialFilterExecution .scheduleCompletion ((adds , mods ) -> {
1250
+ currentMappingFuture .complete (adds .writableCast ().toTracking ());
1251
+ }, currentMappingFuture ::completeExceptionally );
1247
1252
1248
- boolean cancelled = false ;
1249
- TrackingWritableRowSet currentMapping = null ;
1250
1253
try {
1251
- boolean done = false ;
1252
- while (!done ) {
1253
- try {
1254
- currentMapping = currentMappingFuture .get ();
1255
- done = true ;
1256
- } catch (InterruptedException e ) {
1257
- // cancel the job and wait for it to finish cancelling
1258
- cancelled = true ;
1259
- initialFilterExecution .setCancelled ();
1260
- }
1261
- }
1262
- } catch (ExecutionException e ) {
1263
- if (cancelled ) {
1254
+ currentMapping = currentMappingFuture .get ();
1255
+ } catch (ExecutionException | InterruptedException e ) {
1256
+ if (e instanceof InterruptedException ) {
1264
1257
throw new CancellationException ("interrupted while filtering" );
1265
1258
} else if (e .getCause () instanceof RuntimeException ) {
1266
1259
throw (RuntimeException ) e .getCause ();
0 commit comments