From 65c723a74eaa8cba28023f0ee0fc3e71fc4027ef Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 15 Feb 2024 13:32:56 +0000 Subject: [PATCH 1/3] Add docs and renames --- .../EqualityExpressionIndexFilterStrategy.java | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java b/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java index 7ce558be2..57ab68c54 100644 --- a/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java +++ b/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java @@ -62,6 +62,9 @@ private void buildIndex(DataInstance sourceInstance, CompareToNodeExpression pre } } + /** + * Non thread safe index for tree references based on nested string keys (a "section" and an "item"). + */ private static class InMemTreeReferenceIndex { private final Map>> map = new HashMap<>(); @@ -70,22 +73,22 @@ public boolean contains(String section) { return map.containsKey(section); } - public void add(String section, String key, TreeReference reference) { + public void add(String section, String item, TreeReference reference) { if (!map.containsKey(section)) { map.put(section, new HashMap<>()); } Map> sectionMap = map.get(section); - if (!sectionMap.containsKey(key)) { - sectionMap.put(key, new ArrayList<>()); + if (!sectionMap.containsKey(item)) { + sectionMap.put(item, new ArrayList<>()); } - sectionMap.get(key).add(reference); + sectionMap.get(item).add(reference); } - public List lookup(String section, String key) { - if (map.containsKey(section) && map.get(section).containsKey(key)) { - return map.get(section).get(key); + public List lookup(String section, String item) { + if (map.containsKey(section) && map.get(section).containsKey(item)) { + return map.get(section).get(item); } else { return emptyList(); } From 63fedf8cb6c25365f759c1c7e6e5870913944b21 Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 15 Feb 2024 13:37:43 +0000 Subject: [PATCH 2/3] Prevent concurrent modification of equality index --- ...EqualityExpressionIndexFilterStrategy.java | 23 +++++++++++-------- 1 file changed, 13 insertions(+), 10 deletions(-) diff --git a/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java b/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java index 57ab68c54..4ceeed482 100644 --- a/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java +++ b/src/main/java/org/javarosa/core/model/EqualityExpressionIndexFilterStrategy.java @@ -38,9 +38,7 @@ public List filter(@NotNull DataInstance sourceInstance, @NotNull XPathEqExpr original = (XPathEqExpr) candidate.getOriginal(); if (original.isEqual()) { String section = nodeSet + candidate.getNodeSide().toString(); - if (!index.contains(section)) { - buildIndex(sourceInstance, candidate, children, evaluationContext, section); - } + buildIndexIfNeeded(sourceInstance, candidate, children, evaluationContext, section); Object absoluteValue = candidate.evalContextSide(sourceInstance, evaluationContext); return index.lookup(section, absoluteValue.toString()); @@ -52,13 +50,18 @@ public List filter(@NotNull DataInstance sourceInstance, @NotNull } } - private void buildIndex(DataInstance sourceInstance, CompareToNodeExpression predicate, List children, EvaluationContext evaluationContext, String section) { - for (int i = 0; i < children.size(); i++) { - TreeReference child = children.get(i); - - Measure.log("IndexEvaluation"); - String relativeValue = predicate.evalNodeSide(sourceInstance, evaluationContext, child, i).toString(); - index.add(section, relativeValue, child); + /** + * Synchronized to prevent two or more threads from modifying the index at once + */ + private synchronized void buildIndexIfNeeded(DataInstance sourceInstance, CompareToNodeExpression predicate, List children, EvaluationContext evaluationContext, String section) { + if (!index.contains(section)) { + for (int i = 0; i < children.size(); i++) { + TreeReference child = children.get(i); + + Measure.log("IndexEvaluation"); + String relativeValue = predicate.evalNodeSide(sourceInstance, evaluationContext, child, i).toString(); + index.add(section, relativeValue, child); + } } } From 09a8a9526f7912d2044d619f4e15f6c69e8253ad Mon Sep 17 00:00:00 2001 From: Callum Stott Date: Thu, 15 Feb 2024 13:44:03 +0000 Subject: [PATCH 3/3] Prevent concurrent modification in the comparison cache --- .../core/model/ComparisonExpressionCacheFilterStrategy.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/org/javarosa/core/model/ComparisonExpressionCacheFilterStrategy.java b/src/main/java/org/javarosa/core/model/ComparisonExpressionCacheFilterStrategy.java index a1a1cb39a..c92b9aef6 100644 --- a/src/main/java/org/javarosa/core/model/ComparisonExpressionCacheFilterStrategy.java +++ b/src/main/java/org/javarosa/core/model/ComparisonExpressionCacheFilterStrategy.java @@ -56,7 +56,10 @@ public List filter(@NotNull DataInstance sourceInstance, @NotNull } } - private List getCachedEvaluations(@NotNull Supplier> next, String key) { + /** + * Synchronized to prevent two or more threads from modifying {@link #cachedEvaluations} at once + */ + private synchronized List getCachedEvaluations(@NotNull Supplier> next, String key) { if (cachedEvaluations.containsKey(key)) { return cachedEvaluations.get(key); } else {