diff options
author | 2023-09-10 23:07:11 +0200 | |
---|---|---|
committer | 2023-09-10 23:07:11 +0200 | |
commit | c7a86623b1589a3bd68a84a8d54a1eadc1aacefb (patch) | |
tree | 16fb5eb3d3b1282fecedefd9c7ae519162c540da /subprojects/viatra-runtime/src/main/java/tools | |
parent | feat: integrate DSE with partial interpretation (diff) | |
download | refinery-c7a86623b1589a3bd68a84a8d54a1eadc1aacefb.tar.gz refinery-c7a86623b1589a3bd68a84a8d54a1eadc1aacefb.tar.zst refinery-c7a86623b1589a3bd68a84a8d54a1eadc1aacefb.zip |
fix: VIATRA projection indexer error
When a projection indexer is constructed for a production node, the projection
memory is only populated if changes are being propagated. The cache doesn't get
populated even if changes are flushed afterwards. This not only returns invalid
query results, but also a duplicate deletion exception will be thrown when the
production node tries to delete a tuple from the index memory.
To counteract this issue, we enable update propagation while a matcher (and its
associated indexers) are being created.
Diffstat (limited to 'subprojects/viatra-runtime/src/main/java/tools')
2 files changed, 39 insertions, 15 deletions
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java index 4c603a47..0f402b49 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java | |||
@@ -15,6 +15,7 @@ import tools.refinery.viatra.runtime.api.scope.QueryScope; | |||
15 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; | 15 | import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; |
16 | 16 | ||
17 | import java.util.Set; | 17 | import java.util.Set; |
18 | import java.util.function.Supplier; | ||
18 | import java.util.stream.Collectors; | 19 | import java.util.stream.Collectors; |
19 | 20 | ||
20 | /** | 21 | /** |
@@ -147,4 +148,6 @@ public abstract class ViatraQueryEngine { | |||
147 | public abstract QueryScope getScope(); | 148 | public abstract QueryScope getScope(); |
148 | 149 | ||
149 | public abstract void flushChanges(); | 150 | public abstract void flushChanges(); |
151 | |||
152 | public abstract <T> T withFlushingChanges(Supplier<T> supplier); | ||
150 | } | 153 | } |
diff --git a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java index 47a51629..5317a79e 100644 --- a/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java +++ b/subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java | |||
@@ -41,6 +41,7 @@ import java.lang.ref.WeakReference; | |||
41 | import java.lang.reflect.InvocationTargetException; | 41 | import java.lang.reflect.InvocationTargetException; |
42 | import java.util.*; | 42 | import java.util.*; |
43 | import java.util.concurrent.Callable; | 43 | import java.util.concurrent.Callable; |
44 | import java.util.function.Supplier; | ||
44 | import java.util.stream.Collectors; | 45 | import java.util.stream.Collectors; |
45 | 46 | ||
46 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; | 47 | import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; |
@@ -164,9 +165,27 @@ public final class ViatraQueryEngineImpl extends AdvancedViatraQueryEngine | |||
164 | } | 165 | } |
165 | delayMessageDelivery = false; | 166 | delayMessageDelivery = false; |
166 | try { | 167 | try { |
167 | for (IQueryBackend backend : this.queryBackends.values()) { | 168 | flushAllBackends(); |
168 | backend.flushUpdates(); | 169 | } finally { |
169 | } | 170 | delayMessageDelivery = true; |
171 | } | ||
172 | } | ||
173 | |||
174 | private void flushAllBackends() { | ||
175 | for (IQueryBackend backend : this.queryBackends.values()) { | ||
176 | backend.flushUpdates(); | ||
177 | } | ||
178 | } | ||
179 | |||
180 | @Override | ||
181 | public <T> T withFlushingChanges(Supplier<T> callback) { | ||
182 | if (!delayMessageDelivery) { | ||
183 | return callback.get(); | ||
184 | } | ||
185 | delayMessageDelivery = false; | ||
186 | try { | ||
187 | flushAllBackends(); | ||
188 | return callback.get(); | ||
170 | } finally { | 189 | } finally { |
171 | delayMessageDelivery = true; | 190 | delayMessageDelivery = true; |
172 | } | 191 | } |
@@ -186,18 +205,20 @@ public final class ViatraQueryEngineImpl extends AdvancedViatraQueryEngine | |||
186 | @Override | 205 | @Override |
187 | public <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getMatcher( | 206 | public <Matcher extends ViatraQueryMatcher<? extends IPatternMatch>> Matcher getMatcher( |
188 | IQuerySpecification<Matcher> querySpecification, QueryEvaluationHint optionalEvaluationHints) { | 207 | IQuerySpecification<Matcher> querySpecification, QueryEvaluationHint optionalEvaluationHints) { |
189 | IMatcherCapability capability = getRequestedCapability(querySpecification, optionalEvaluationHints); | 208 | return withFlushingChanges(() -> { |
190 | Matcher matcher = doGetExistingMatcher(querySpecification, capability); | 209 | IMatcherCapability capability = getRequestedCapability(querySpecification, optionalEvaluationHints); |
191 | if (matcher != null) { | 210 | Matcher matcher = doGetExistingMatcher(querySpecification, capability); |
192 | return matcher; | 211 | if (matcher != null) { |
193 | } | 212 | return matcher; |
194 | matcher = querySpecification.instantiate(); | 213 | } |
195 | 214 | matcher = querySpecification.instantiate(); | |
196 | BaseMatcher<?> baseMatcher = (BaseMatcher<?>) matcher; | 215 | |
197 | ((QueryResultWrapper) baseMatcher).setBackend(this, | 216 | BaseMatcher<?> baseMatcher = (BaseMatcher<?>) matcher; |
198 | getResultProvider(querySpecification, optionalEvaluationHints), capability); | 217 | ((QueryResultWrapper) baseMatcher).setBackend(this, |
199 | internalRegisterMatcher(querySpecification, baseMatcher); | 218 | getResultProvider(querySpecification, optionalEvaluationHints), capability); |
200 | return matcher; | 219 | internalRegisterMatcher(querySpecification, baseMatcher); |
220 | return matcher; | ||
221 | }); | ||
201 | } | 222 | } |
202 | 223 | ||
203 | @Override | 224 | @Override |