aboutsummaryrefslogtreecommitdiffstats
path: root/subprojects/viatra-runtime/src/main/java/tools
diff options
context:
space:
mode:
authorLibravatar Kristóf Marussy <kristof@marussy.com>2023-09-10 23:07:11 +0200
committerLibravatar Kristóf Marussy <kristof@marussy.com>2023-09-10 23:07:11 +0200
commitc7a86623b1589a3bd68a84a8d54a1eadc1aacefb (patch)
tree16fb5eb3d3b1282fecedefd9c7ae519162c540da /subprojects/viatra-runtime/src/main/java/tools
parentfeat: integrate DSE with partial interpretation (diff)
downloadrefinery-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')
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/api/ViatraQueryEngine.java3
-rw-r--r--subprojects/viatra-runtime/src/main/java/tools/refinery/viatra/runtime/internal/apiimpl/ViatraQueryEngineImpl.java51
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;
15import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException; 15import tools.refinery.viatra.runtime.matchers.ViatraQueryRuntimeException;
16 16
17import java.util.Set; 17import java.util.Set;
18import java.util.function.Supplier;
18import java.util.stream.Collectors; 19import 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;
41import java.lang.reflect.InvocationTargetException; 41import java.lang.reflect.InvocationTargetException;
42import java.util.*; 42import java.util.*;
43import java.util.concurrent.Callable; 43import java.util.concurrent.Callable;
44import java.util.function.Supplier;
44import java.util.stream.Collectors; 45import java.util.stream.Collectors;
45 46
46import static tools.refinery.viatra.runtime.matchers.util.Preconditions.checkArgument; 47import 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