Skip to main content
aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorEike Stepper2017-05-31 07:41:29 -0400
committerEike Stepper2017-05-31 07:41:29 -0400
commit8d700f079db51c61a776e3cdc7c0a2b472d12c15 (patch)
tree30b18f21637ce0708e1826ca3d8cfac422d9793b
parent2cb4a4dfe5f5e0e1efd3311205dec6e30bf6292d (diff)
downloadcdo-8d700f079db51c61a776e3cdc7c0a2b472d12c15.tar.gz
cdo-8d700f079db51c61a776e3cdc7c0a2b472d12c15.tar.xz
cdo-8d700f079db51c61a776e3cdc7c0a2b472d12c15.zip
[517168] CDOView.queryXRef returns invalid values when an object is removed on a newly created CDO branch
https://bugs.eclipse.org/bugs/show_bug.cgi?id=517168
-rw-r--r--plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java167
-rw-r--r--plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_517168_Test.java138
2 files changed, 261 insertions, 44 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java
index fff86f0e83..459ef34391 100644
--- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java
+++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/XRefsQueryHandler.java
@@ -23,6 +23,7 @@ import org.eclipse.emf.cdo.common.model.CDOPackageRegistry;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit;
import org.eclipse.emf.cdo.common.model.CDOPackageUnit.State;
import org.eclipse.emf.cdo.common.protocol.CDOProtocolConstants;
+import org.eclipse.emf.cdo.common.revision.CDORevision;
import org.eclipse.emf.cdo.common.util.CDOQueryInfo;
import org.eclipse.emf.cdo.server.IQueryContext;
import org.eclipse.emf.cdo.server.IQueryHandler;
@@ -32,7 +33,11 @@ import org.eclipse.emf.cdo.server.IStoreAccessor;
import org.eclipse.emf.cdo.server.IView;
import org.eclipse.emf.cdo.server.StoreThreadLocal;
import org.eclipse.emf.cdo.server.StoreThreadLocal.NoSessionRegisteredException;
+import org.eclipse.emf.cdo.spi.common.branch.CDOBranchUtil;
import org.eclipse.emf.cdo.spi.common.model.InternalCDOPackageRegistry;
+import org.eclipse.emf.cdo.spi.common.revision.DetachedCDORevision;
+import org.eclipse.emf.cdo.spi.common.revision.InternalCDORevisionManager;
+import org.eclipse.emf.cdo.spi.common.revision.SyntheticCDORevision;
import org.eclipse.emf.cdo.spi.server.InternalRepository;
import org.eclipse.emf.cdo.spi.server.QueryHandlerFactory;
@@ -47,8 +52,10 @@ import org.eclipse.emf.ecore.EcorePackage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
+import java.util.HashSet;
import java.util.List;
import java.util.Map;
+import java.util.Set;
import java.util.StringTokenizer;
/**
@@ -65,20 +72,29 @@ public class XRefsQueryHandler implements IQueryHandler
try
{
IStoreAccessor accessor = StoreThreadLocal.getAccessor();
- QueryContext xrefsContext = new QueryContext(info, context);
- accessor.queryXRefs(xrefsContext);
CDOBranchPoint branchPoint = context;
CDOBranch branch = branchPoint.getBranch();
- int maxResults = info.getMaxResults();
- while (!branch.isMainBranch() && (maxResults == CDOQueryInfo.UNLIMITED_RESULTS || context.getResultCount() < maxResults))
+ if (branch.isMainBranch())
{
- branchPoint = branch.getBase();
- branch = branchPoint.getBranch();
-
- xrefsContext.setBranchPoint(branchPoint);
+ QueryContext xrefsContext = new QueryContext(info, context);
+ accessor.queryXRefs(xrefsContext);
+ }
+ else
+ {
+ QueryContext xrefsContext = new QueryContextBranching(info, context);
accessor.queryXRefs(xrefsContext);
+
+ int maxResults = info.getMaxResults();
+ while (!branch.isMainBranch() && (maxResults == CDOQueryInfo.UNLIMITED_RESULTS || context.getResultCount() < maxResults))
+ {
+ branchPoint = branch.getBase();
+ branch = branchPoint.getBranch();
+
+ xrefsContext.setBranchPoint(branchPoint);
+ accessor.queryXRefs(xrefsContext);
+ }
}
}
catch (NoSessionRegisteredException ex)
@@ -208,7 +224,7 @@ public class XRefsQueryHandler implements IQueryHandler
* @author Eike Stepper
* @since 3.0
*/
- private static final class QueryContext implements IStoreAccessor.QueryXRefsContext
+ private static class QueryContext implements IStoreAccessor.QueryXRefsContext
{
private CDOQueryInfo info;
@@ -229,26 +245,26 @@ public class XRefsQueryHandler implements IQueryHandler
branchPoint = context;
}
- public void setBranchPoint(CDOBranchPoint branchPoint)
+ public final void setBranchPoint(CDOBranchPoint branchPoint)
{
this.branchPoint = branchPoint;
}
- public CDOBranch getBranch()
+ public final CDOBranch getBranch()
{
return branchPoint.getBranch();
}
- public long getTimeStamp()
+ public final long getTimeStamp()
{
return branchPoint.getTimeStamp();
}
- public Map<CDOID, EClass> getTargetObjects()
+ public final Map<CDOID, EClass> getTargetObjects()
{
if (targetObjects == null)
{
- IRepository repository = context.getView().getRepository();
+ IRepository repository = getRepository();
IStore store = repository.getStore();
CDOPackageRegistry packageRegistry = repository.getPackageRegistry();
@@ -287,7 +303,7 @@ public class XRefsQueryHandler implements IQueryHandler
return targetObjects;
}
- public EReference[] getSourceReferences()
+ public final EReference[] getSourceReferences()
{
if (sourceReferences == null)
{
@@ -297,10 +313,66 @@ public class XRefsQueryHandler implements IQueryHandler
return sourceReferences;
}
+ public final Map<EClass, List<EReference>> getSourceCandidates()
+ {
+ if (sourceCandidates == null)
+ {
+ sourceCandidates = new HashMap<EClass, List<EReference>>();
+ Collection<EClass> concreteTypes = getTargetObjects().values();
+ EReference[] sourceReferences = getSourceReferences();
+
+ if (sourceReferences.length != 0)
+ {
+ InternalRepository repository = (InternalRepository)getRepository();
+ InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
+ for (EReference eReference : sourceReferences)
+ {
+ collectSourceCandidates(eReference, concreteTypes, sourceCandidates, packageRegistry);
+ }
+ }
+ else
+ {
+ collectSourceCandidates(context.getView(), concreteTypes, sourceCandidates);
+ }
+ }
+
+ return sourceCandidates;
+ }
+
+ public final int getMaxResults()
+ {
+ return info.getMaxResults();
+ }
+
+ public final IRepository getRepository()
+ {
+ return context.getView().getRepository();
+ }
+
+ public final boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
+ {
+ if (CDOIDUtil.isNull(targetID))
+ {
+ return true;
+ }
+
+ if (isIgnoredObject(sourceID))
+ {
+ return true;
+ }
+
+ return context.addResult(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
+ }
+
+ protected boolean isIgnoredObject(CDOID sourceID)
+ {
+ return false;
+ }
+
private EReference[] parseSourceReferences()
{
List<EReference> result = new ArrayList<EReference>();
- CDOPackageRegistry packageRegistry = context.getView().getRepository().getPackageRegistry();
+ CDOPackageRegistry packageRegistry = getRepository().getPackageRegistry();
String params = (String)info.getParameters().get(CDOProtocolConstants.QUERY_LANGUAGE_XREFS_SOURCE_REFERENCES);
if (params == null)
@@ -322,46 +394,53 @@ public class XRefsQueryHandler implements IQueryHandler
return result.toArray(new EReference[result.size()]);
}
+ }
- public Map<EClass, List<EReference>> getSourceCandidates()
- {
- if (sourceCandidates == null)
- {
- sourceCandidates = new HashMap<EClass, List<EReference>>();
- Collection<EClass> concreteTypes = getTargetObjects().values();
- EReference[] sourceReferences = getSourceReferences();
+ /**
+ * @author Eike Stepper
+ */
+ private static final class QueryContextBranching extends QueryContext
+ {
+ private final CDOBranchPoint originalBranchPoint;
- if (sourceReferences.length != 0)
- {
- InternalRepository repository = (InternalRepository)context.getView().getRepository();
- InternalCDOPackageRegistry packageRegistry = repository.getPackageRegistry(false);
- for (EReference eReference : sourceReferences)
- {
- collectSourceCandidates(eReference, concreteTypes, sourceCandidates, packageRegistry);
- }
- }
- else
- {
- collectSourceCandidates(context.getView(), concreteTypes, sourceCandidates);
- }
- }
+ private final Set<CDOID> ignoredObjects = new HashSet<CDOID>();
- return sourceCandidates;
+ public QueryContextBranching(CDOQueryInfo info, IQueryContext context)
+ {
+ super(info, context);
+ originalBranchPoint = CDOBranchUtil.copyBranchPoint(context);
}
- public int getMaxResults()
+ @Override
+ protected boolean isIgnoredObject(CDOID sourceID)
{
- return info.getMaxResults();
+ if (!ignoredObjects.add(sourceID))
+ {
+ return true;
+ }
+
+ if (isDetachedObject(sourceID))
+ {
+ ignoredObjects.add(sourceID);
+ return true;
+ }
+
+ return false;
}
- public boolean addXRef(CDOID targetID, CDOID sourceID, EReference sourceReference, int sourceIndex)
+ private boolean isDetachedObject(CDOID sourceID)
{
- if (CDOIDUtil.isNull(targetID))
+ if (getBranch() == originalBranchPoint.getBranch())
{
- return true;
+ return false;
}
- return context.addResult(new CDOIDReference(targetID, sourceID, sourceReference, sourceIndex));
+ SyntheticCDORevision[] synthetics = { null };
+
+ InternalCDORevisionManager revisionManager = (InternalCDORevisionManager)getRepository().getRevisionManager();
+ revisionManager.getRevision(sourceID, originalBranchPoint, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true, synthetics);
+
+ return synthetics[0] instanceof DetachedCDORevision;
}
}
diff --git a/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_517168_Test.java b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_517168_Test.java
new file mode 100644
index 0000000000..1621ee2fae
--- /dev/null
+++ b/plugins/org.eclipse.emf.cdo.tests/src/org/eclipse/emf/cdo/tests/bugzilla/Bugzilla_517168_Test.java
@@ -0,0 +1,138 @@
+/*
+ * Copyright (c) 2016 Eike Stepper (Berlin, Germany) and others.
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License v1.0
+ * which accompanies this distribution, and is available at
+ * http://www.eclipse.org/legal/epl-v10.html
+ *
+ * Contributors:
+ * Eike Stepper - initial API and implementation
+ */
+package org.eclipse.emf.cdo.tests.bugzilla;
+
+import org.eclipse.emf.cdo.CDOObjectReference;
+import org.eclipse.emf.cdo.common.branch.CDOBranch;
+import org.eclipse.emf.cdo.eresource.CDOResource;
+import org.eclipse.emf.cdo.session.CDOSession;
+import org.eclipse.emf.cdo.tests.AbstractCDOTest;
+import org.eclipse.emf.cdo.tests.config.IRepositoryConfig;
+import org.eclipse.emf.cdo.tests.config.impl.ConfigTest.Requires;
+import org.eclipse.emf.cdo.tests.model1.OrderDetail;
+import org.eclipse.emf.cdo.tests.model1.Product1;
+import org.eclipse.emf.cdo.tests.model1.PurchaseOrder;
+import org.eclipse.emf.cdo.tests.model1.SalesOrder;
+import org.eclipse.emf.cdo.transaction.CDOTransaction;
+import org.eclipse.emf.cdo.util.CDOUtil;
+
+import org.eclipse.emf.ecore.util.EcoreUtil;
+
+import java.util.List;
+
+/**
+ * Bug 517168: Multiple revision instances are loaded during branch switchCDOView.queryXRef
+ * returns invalid values when an object is removed on a newly created CDO branch.
+ *
+ * @author Eike Stepper
+ */
+@Requires(IRepositoryConfig.CAPABILITY_BRANCHING)
+public class Bugzilla_517168_Test extends AbstractCDOTest
+{
+ public void testDeletedXRef_SingleValue() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+
+ // Initialize main branch with two objects, an order detail with a given product.
+ Product1 product = getModel1Factory().createProduct1();
+ OrderDetail orderDetail = getModel1Factory().createOrderDetail();
+ orderDetail.setProduct(product);
+
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+ resource.getContents().add(product);
+ resource.getContents().add(orderDetail);
+ transaction.commit();
+
+ // Create a branch and open a transaction on it.
+ CDOBranch derivedBranch = transaction.getBranch().createBranch("Derived");
+ transaction = session.openTransaction(derivedBranch);
+ orderDetail = transaction.getObject(orderDetail);
+ product = transaction.getObject(product);
+
+ // Remove the order detail and commit the removal.
+ EcoreUtil.delete(orderDetail);
+ transaction.commit();
+
+ // Check XRef API on derived branch after object removal:
+ // An empty result is supposed to be retrieved at this point.
+ List<CDOObjectReference> xRefs = transaction.queryXRefs(CDOUtil.getCDOObject(product));
+ assertEquals(0, xRefs.size());
+ }
+
+ public void testDeletedXRef_ManyValue() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+
+ // Initialize main branch with two objects, an order detail with a given product.
+ PurchaseOrder purchaseOrder = getModel1Factory().createPurchaseOrder();
+ SalesOrder salesOrder = getModel1Factory().createSalesOrder();
+ salesOrder.getPurchaseOrders().add(purchaseOrder);
+
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+ resource.getContents().add(purchaseOrder);
+ resource.getContents().add(salesOrder);
+ transaction.commit();
+
+ // Create a branch and open a transaction on it.
+ CDOBranch derivedBranch = transaction.getBranch().createBranch("Derived");
+ transaction = session.openTransaction(derivedBranch);
+ salesOrder = transaction.getObject(salesOrder);
+ purchaseOrder = transaction.getObject(purchaseOrder);
+
+ // Check XRef API on derived branch:
+ // The customer is supposed to be retrieved at this point.
+ List<CDOObjectReference> xRefs = transaction.queryXRefs(CDOUtil.getCDOObject(purchaseOrder));
+ assertEquals(1, xRefs.size());
+ assertEquals(salesOrder, xRefs.get(0).getSourceObject());
+
+ // Remove the order detail and commit the removal.
+ EcoreUtil.delete(salesOrder);
+ transaction.commit();
+
+ // Check XRef API on derived branch after object removal:
+ // An empty result is supposed to be retrieved at this point.
+ xRefs = transaction.queryXRefs(CDOUtil.getCDOObject(purchaseOrder));
+ assertEquals(0, xRefs.size());
+ }
+
+ public void testDuplicateXRef_SingleValue() throws Exception
+ {
+ CDOSession session = openSession();
+ CDOTransaction transaction = session.openTransaction();
+
+ // Initialize main branch with two objects, an order detail with a given product.
+ Product1 product = getModel1Factory().createProduct1();
+ OrderDetail orderDetail = getModel1Factory().createOrderDetail();
+ orderDetail.setProduct(product);
+
+ CDOResource resource = transaction.createResource(getResourcePath("res"));
+ resource.getContents().add(product);
+ resource.getContents().add(orderDetail);
+ transaction.commit();
+
+ // Create a branch and open a transaction on it.
+ CDOBranch derivedBranch = transaction.getBranch().createBranch("Derived");
+ transaction = session.openTransaction(derivedBranch);
+ orderDetail = transaction.getObject(orderDetail);
+ product = transaction.getObject(product);
+
+ // Change an attribute of the order detail and commit the change.
+ orderDetail.setPrice(47.11f);
+ transaction.commit();
+
+ // Check XRef API on derived branch after object removal:
+ // An empty result is supposed to be retrieved at this point.
+ List<CDOObjectReference> xRefs = transaction.queryXRefs(CDOUtil.getCDOObject(product));
+ assertEquals(1, xRefs.size());
+ }
+}

Back to the top