You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@cayenne.apache.org by nt...@apache.org on 2018/07/27 14:30:30 UTC
[2/2] cayenne git commit: CAY-2446 Run Disjoint By Id queries outside
of synchronized block
CAY-2446 Run Disjoint By Id queries outside of synchronized block
Project: http://git-wip-us.apache.org/repos/asf/cayenne/repo
Commit: http://git-wip-us.apache.org/repos/asf/cayenne/commit/8339c199
Tree: http://git-wip-us.apache.org/repos/asf/cayenne/tree/8339c199
Diff: http://git-wip-us.apache.org/repos/asf/cayenne/diff/8339c199
Branch: refs/heads/master
Commit: 8339c19959aa9bc6e0e05b1536af5622b13ae670
Parents: 28af933
Author: Nikita Timofeev <st...@gmail.com>
Authored: Fri Jul 27 17:30:13 2018 +0300
Committer: Nikita Timofeev <st...@gmail.com>
Committed: Fri Jul 27 17:30:13 2018 +0300
----------------------------------------------------------------------
RELEASE-NOTES.txt | 2 +
.../access/HierarchicalObjectResolver.java | 142 ++++++++++++-------
2 files changed, 89 insertions(+), 55 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8339c199/RELEASE-NOTES.txt
----------------------------------------------------------------------
diff --git a/RELEASE-NOTES.txt b/RELEASE-NOTES.txt
index b52a4f3..8db9264 100644
--- a/RELEASE-NOTES.txt
+++ b/RELEASE-NOTES.txt
@@ -13,6 +13,8 @@ Date:
----------------------------------
Changes/New Features:
+CAY-2446 Run Disjoint By Id queries outside of synchronized block
+
Bug Fixes:
CAY-2444 Change URI from http:// to https:// in xsi:schemaLocation
http://git-wip-us.apache.org/repos/asf/cayenne/blob/8339c199/cayenne-server/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
----------------------------------------------------------------------
diff --git a/cayenne-server/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java b/cayenne-server/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
index e24209c..201f304 100644
--- a/cayenne-server/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
+++ b/cayenne-server/src/main/java/org/apache/cayenne/access/HierarchicalObjectResolver.java
@@ -59,74 +59,54 @@ class HierarchicalObjectResolver {
}
HierarchicalObjectResolver(DataContext context, QueryMetadata metadata,
- ClassDescriptor descriptor, boolean needToSaveDuplicates) {
+ ClassDescriptor descriptor, boolean needToSaveDuplicates) {
this(context, metadata);
this.descriptor = descriptor;
this.needToSaveDuplicates = needToSaveDuplicates;
}
/**
- * Properly synchronized version of 'resolveObjectTree'.
+ * Properly synchronized object resolution
*/
PrefetchProcessorNode synchronizedRootResultNodeFromDataRows(
PrefetchTreeNode tree,
List<DataRow> mainResultRows,
Map<String, List<?>> extraResultsByPath) {
- synchronized (context.getObjectStore()) {
- return resolveObjectTree(tree, mainResultRows, extraResultsByPath);
- }
- }
-
- private PrefetchProcessorNode resolveObjectTree(
- PrefetchTreeNode tree,
- List<DataRow> mainResultRows,
- Map<String, List<?>> extraResultsByPath) {
+ PrefetchProcessorNode decoratedTree = decorateTree(tree, mainResultRows, extraResultsByPath);
- // create a copy of the tree using DecoratedPrefetchNodes and then traverse it
- // resolving objects...
- PrefetchProcessorNode decoratedTree = new PrefetchProcessorTreeBuilder(
- this,
- mainResultRows,
- extraResultsByPath).buildTree(tree);
+ // prepare data for disjoint by id prefetches
+ decoratedTree.traverse(new DisjointByIdProcessor());
- // do a single path for disjoint prefetches, joint subtrees will be processed at
- // each disjoint node that is a parent of joint prefetches.
- decoratedTree.traverse(new DisjointProcessor());
+ // resolve objects under global lock to keep object graph consistent
+ synchronized (context.getObjectStore()) {
+ // do a single path for disjoint prefetches, joint subtrees will be processed at
+ // each disjoint node that is a parent of joint prefetches.
+ decoratedTree.traverse(new DisjointProcessor());
- // connect related objects
- decoratedTree.traverse(new PostProcessor());
+ // connect related objects
+ decoratedTree.traverse(new PostProcessor());
+ }
return decoratedTree;
}
- final class DisjointProcessor implements PrefetchProcessor {
-
- @Override
- public boolean startDisjointPrefetch(PrefetchTreeNode node) {
-
- PrefetchProcessorNode processorNode = (PrefetchProcessorNode) node;
-
- // this means something bad happened during fetch
- if (processorNode.getDataRows() == null) {
- return false;
- }
-
- // continue with processing even if the objects list is empty to handle multi-step prefetches.
- if (processorNode.getDataRows().isEmpty()) {
- return true;
- }
-
- List<Persistent> objects = processorNode.getResolver().objectsFromDataRows(processorNode.getDataRows());
- processorNode.setObjects(objects);
+ /**
+ * create a copy of the tree using DecoratedPrefetchNodes and then traverse it resolving objects...
+ */
+ private PrefetchProcessorNode decorateTree(PrefetchTreeNode tree,
+ List<DataRow> mainResultRows,
+ Map<String, List<?>> extraResultsByPath) {
+ return new PrefetchProcessorTreeBuilder(this, mainResultRows, extraResultsByPath)
+ .buildTree(tree);
+ }
- return true;
- }
+ final class DisjointByIdProcessor implements PrefetchProcessor {
@Override
public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
if (node.getParent().isPhantom()) {
- // TODO: doing nothing in current implementation if parent node is phantom
+ // doing nothing in current implementation if parent node is phantom
return true;
}
@@ -139,7 +119,6 @@ class HierarchicalObjectResolver {
String pathPrefix = "";
if (dbRelationships.size() > 1) {
-
// we need path prefix for flattened relationships
StringBuilder buffer = new StringBuilder();
for (int i = dbRelationships.size() - 1; i >= 1; i--) {
@@ -154,14 +133,14 @@ class HierarchicalObjectResolver {
}
List<DataRow> parentDataRows;
-
- // note that a disjoint prefetch that has adjacent joint prefetches
- // will be a PrefetchProcessorJointNode, so here check for semantics, not node type
- if (parentProcessorNode.getSemantics() == PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS) {
- parentDataRows = ((PrefetchProcessorJointNode) parentProcessorNode).getResolvedRows();
- } else {
- parentDataRows = parentProcessorNode.getDataRows();
- }
+
+ // note that a disjoint prefetch that has adjacent joint prefetches
+ // will be a PrefetchProcessorJointNode, so here check for semantics, not node type
+ if (parentProcessorNode.getSemantics() == PrefetchTreeNode.JOINT_PREFETCH_SEMANTICS) {
+ parentDataRows = ((PrefetchProcessorJointNode) parentProcessorNode).getResolvedRows();
+ } else {
+ parentDataRows = parentProcessorNode.getDataRows();
+ }
int maxIdQualifierSize = context.getParentDataDomain().getMaxIdQualifierSize();
List<DbJoin> joins = lastDbRelationship.getJoins();
@@ -221,7 +200,7 @@ class HierarchicalObjectResolver {
}
processorNode.setDataRows(dataRows);
- return startDisjointPrefetch(node);
+ return true;
}
private void createDisjointByIdPrefetchQualifier(String pathPrefix, PrefetchSelectQuery currentQuery,
@@ -249,6 +228,59 @@ class HierarchicalObjectResolver {
}
@Override
+ public boolean startPhantomPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+
+ @Override
+ public boolean startDisjointPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+
+ @Override
+ public boolean startJointPrefetch(PrefetchTreeNode node) {
+ return true;
+ }
+
+ @Override
+ public boolean startUnknownPrefetch(PrefetchTreeNode node) {
+ throw new CayenneRuntimeException("Unknown prefetch node: %s", node);
+ }
+
+ @Override
+ public void finishPrefetch(PrefetchTreeNode node) {
+ }
+ }
+
+ final class DisjointProcessor implements PrefetchProcessor {
+
+ @Override
+ public boolean startDisjointPrefetch(PrefetchTreeNode node) {
+
+ PrefetchProcessorNode processorNode = (PrefetchProcessorNode) node;
+
+ // this means something bad happened during fetch
+ if (processorNode.getDataRows() == null) {
+ return false;
+ }
+
+ // continue with processing even if the objects list is empty to handle multi-step prefetches.
+ if (processorNode.getDataRows().isEmpty()) {
+ return true;
+ }
+
+ List<Persistent> objects = processorNode.getResolver().objectsFromDataRows(processorNode.getDataRows());
+ processorNode.setObjects(objects);
+
+ return true;
+ }
+
+ @Override
+ public boolean startDisjointByIdPrefetch(PrefetchTreeNode node) {
+ return startDisjointPrefetch(node);
+ }
+
+ @Override
public boolean startJointPrefetch(PrefetchTreeNode node) {
// delegate processing of the top level joint prefetch to a joint processor,
@@ -332,7 +364,7 @@ class HierarchicalObjectResolver {
// a processor of a single joint result set that walks a subtree of prefetch nodes
// that use this result set.
- final class JointProcessor implements PrefetchProcessor {
+ final static class JointProcessor implements PrefetchProcessor {
DataRow currentFlatRow;
PrefetchProcessorNode rootNode;