diff options
author | Esteban Dugueperoux | 2015-05-14 10:10:00 +0000 |
---|---|---|
committer | Eike Stepper | 2015-05-14 10:10:00 +0000 |
commit | fe0aaaf61faac3cab201cb5f3b16fec4f903c9b9 (patch) | |
tree | be0e115cf3ba98a892c42f651615a3ed74a4c3ee | |
parent | 7df57d3fa62a72f10d30e38bc1b389da09b25fa3 (diff) | |
download | cdo-fe0aaaf61faac3cab201cb5f3b16fec4f903c9b9.tar.gz cdo-fe0aaaf61faac3cab201cb5f3b16fec4f903c9b9.tar.xz cdo-fe0aaaf61faac3cab201cb5f3b16fec4f903c9b9.zip |
[363695] Have stale references cleanup in option
Have stale references cleanup in option during invalidation.
Task-Url: https://bugs.eclipse.org/bugs/show_bug.cgi?id=363695
Change-Id: Icff9932127a51dc01ad435ba7c68085a360a8646
Signed-off-by: Esteban Dugueperoux <esteban.dugueperoux@obeo.fr>
Signed-off-by: Eike Stepper <stepper@esc-net.de>
3 files changed, 155 insertions, 29 deletions
diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOStaleReferenceCleaner.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOStaleReferenceCleaner.java new file mode 100644 index 0000000000..a492b8750b --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOStaleReferenceCleaner.java @@ -0,0 +1,53 @@ +/* + * Copyright (c) 2015 Obeo 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: + * Esteban Dugueperoux - initial API and implementation + */ +package org.eclipse.emf.cdo.transaction; + +import org.eclipse.net4j.util.collection.Pair; + +import org.eclipse.emf.ecore.EObject; +import org.eclipse.emf.ecore.EStructuralFeature.Setting; +import org.eclipse.emf.ecore.util.EcoreUtil; + +import java.util.Collection; + +/** + * Interface to externalize the cleaning of stale references created on invalidation. + * + * @author Esteban Dugueperoux + * @since 4.4 + */ +public interface CDOStaleReferenceCleaner +{ + public static final CDOStaleReferenceCleaner DEFAULT = new Default(); + + /** + * Clean the stale references created on invalidation. + * + * @param objectsToBeRemoved {@link Collection} of {@link Pair} from {@link Setting} to detached objects + */ + public void cleanStaleReferences(Collection<Pair<Setting, EObject>> objectsToBeRemoved); + + /** + * A default {@link CDOStaleReferenceCleaner} that can be used on invalidation. + * + * @author Esteban Dugueperoux + */ + public static class Default implements CDOStaleReferenceCleaner + { + public void cleanStaleReferences(Collection<Pair<Setting, EObject>> objectsToBeRemoved) + { + for (Pair<Setting, EObject> pair : objectsToBeRemoved) + { + EcoreUtil.remove(pair.getElement1(), pair.getElement2()); + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java index db32e3bec3..3a21150d78 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOTransaction.java @@ -271,6 +271,22 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr public void removeConflictResolver(CDOConflictResolver resolver); /** + * Get the {@link CDOStaleReferenceCleaner} to be used to clean stale references when receiving + * remote changes on invalidation. + * + * @since 4.4 + */ + public CDOStaleReferenceCleaner getStaleReferenceCleaner(); + + /** + * Set the {@link CDOStaleReferenceCleaner} to be used to clean stale references when receiving + * remote changes on invalidation. + * + * @since 4.4 + */ + public void setStaleReferenceCleaner(CDOStaleReferenceCleaner staleReferenceCleaner); + + /** * Returns true if locks in this view will be removes when {@link CDOTransaction#commit()} or * {@link CDOTransaction#rollback()} is called. * <p> @@ -315,6 +331,19 @@ public interface CDOTransaction extends CDOView, CDOCommonTransaction, CDOUserTr /** * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the + * {@link Options#setStaleReferenceCleaner(CDOStaleReferenceCleaner) stale reference cleaner} option has changed. + * + * @author Eike Stepper + * @since 4.4 + * @noextend This interface is not intended to be extended by clients. + * @noimplement This interface is not intended to be implemented by clients. + */ + public interface StaleReferenceCleanerEvent extends IOptionsEvent + { + } + + /** + * An {@link IOptionsEvent options event} fired from transaction {@link CDOTransaction#options() options} when the * {@link Options#setAutoReleaseLocksEnabled(boolean) auto release locks} option has changed. * * @author Eike Stepper diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java index b7a397796a..ccf6ca82bf 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/transaction/CDOTransactionImpl.java @@ -18,7 +18,6 @@ package org.eclipse.emf.internal.cdo.transaction; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.CDOState; import org.eclipse.emf.cdo.common.CDOCommonRepository; -import org.eclipse.emf.cdo.common.CDOCommonRepository.IDGenerationLocation; import org.eclipse.emf.cdo.common.branch.CDOBranch; import org.eclipse.emf.cdo.common.branch.CDOBranchManager; import org.eclipse.emf.cdo.common.branch.CDOBranchPoint; @@ -36,7 +35,7 @@ import org.eclipse.emf.cdo.common.id.CDOIDUtil; import org.eclipse.emf.cdo.common.id.CDOIdentifiable; import org.eclipse.emf.cdo.common.lob.CDOLob; import org.eclipse.emf.cdo.common.lob.CDOLobStore; -import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo.Operation; +import org.eclipse.emf.cdo.common.lock.CDOLockChangeInfo; import org.eclipse.emf.cdo.common.lock.CDOLockOwner; import org.eclipse.emf.cdo.common.lock.CDOLockState; import org.eclipse.emf.cdo.common.lock.CDOLockUtil; @@ -46,7 +45,7 @@ import org.eclipse.emf.cdo.common.model.CDOPackageUnit; import org.eclipse.emf.cdo.common.model.EMFUtil; import org.eclipse.emf.cdo.common.protocol.CDODataInput; import org.eclipse.emf.cdo.common.protocol.CDODataOutput; -import org.eclipse.emf.cdo.common.protocol.CDOProtocol.CommitNotificationInfo; +import org.eclipse.emf.cdo.common.protocol.CDOProtocol; import org.eclipse.emf.cdo.common.revision.CDOIDAndVersion; import org.eclipse.emf.cdo.common.revision.CDOList; import org.eclipse.emf.cdo.common.revision.CDOListFactory; @@ -93,6 +92,7 @@ import org.eclipse.emf.cdo.transaction.CDOConflictResolver2; import org.eclipse.emf.cdo.transaction.CDODefaultTransactionHandler1; import org.eclipse.emf.cdo.transaction.CDOMerger; import org.eclipse.emf.cdo.transaction.CDOSavepoint; +import org.eclipse.emf.cdo.transaction.CDOStaleReferenceCleaner; import org.eclipse.emf.cdo.transaction.CDOTransaction; import org.eclipse.emf.cdo.transaction.CDOTransactionConflictEvent; import org.eclipse.emf.cdo.transaction.CDOTransactionFinishedEvent; @@ -131,7 +131,7 @@ import org.eclipse.net4j.util.WrappedException; import org.eclipse.net4j.util.collection.ByteArrayWrapper; import org.eclipse.net4j.util.collection.ConcurrentArray; import org.eclipse.net4j.util.collection.Pair; -import org.eclipse.net4j.util.concurrent.IRWLockManager.LockType; +import org.eclipse.net4j.util.concurrent.IRWLockManager; import org.eclipse.net4j.util.concurrent.TimeoutRuntimeException; import org.eclipse.net4j.util.event.IEvent; import org.eclipse.net4j.util.event.IListener; @@ -149,15 +149,11 @@ import org.eclipse.emf.ecore.EObject; import org.eclipse.emf.ecore.EPackage; import org.eclipse.emf.ecore.EReference; import org.eclipse.emf.ecore.EStructuralFeature; -import org.eclipse.emf.ecore.EStructuralFeature.Setting; import org.eclipse.emf.ecore.InternalEObject; -import org.eclipse.emf.ecore.impl.EClassImpl.FeatureSubsetSupplier; +import org.eclipse.emf.ecore.impl.EClassImpl; import org.eclipse.emf.ecore.resource.Resource; -import org.eclipse.emf.ecore.resource.Resource.Internal; import org.eclipse.emf.ecore.util.EContentsEList; -import org.eclipse.emf.ecore.util.EContentsEList.FeatureIterator; import org.eclipse.emf.ecore.util.ECrossReferenceEList; -import org.eclipse.emf.ecore.util.EcoreUtil; import org.eclipse.emf.spi.cdo.CDOSessionProtocol; import org.eclipse.emf.spi.cdo.CDOSessionProtocol.CommitTransactionResult; import org.eclipse.emf.spi.cdo.CDOTransactionStrategy; @@ -523,7 +519,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa // Merges from local offline branches may require additional ID mappings: localID -> tempID if (source != null && source.getBranch().isLocal() - && getSession().getRepositoryInfo().getIDGenerationLocation() == IDGenerationLocation.STORE) + && getSession().getRepositoryInfo().getIDGenerationLocation() == CDOCommonRepository.IDGenerationLocation.STORE) { applyLocalIDMapping(changeSetData, result); } @@ -1384,7 +1380,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (idOrObject instanceof CDOObjectImpl) { CDOObjectImpl impl = (CDOObjectImpl)idOrObject; - Internal directResource = impl.eDirectResource(); + Resource.Internal directResource = impl.eDirectResource(); EObject container = impl.eContainer(); if (!toBeDetached.contains(directResource) && !toBeDetached.contains(container)) { @@ -1395,7 +1391,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa else if (idOrObject instanceof CDOObjectWrapper) { CDOObjectWrapper wrapper = (CDOObjectWrapper)idOrObject; - Internal directResource = wrapper.eDirectResource(); + Resource.Internal directResource = wrapper.eDirectResource(); EObject container = wrapper.eContainer(); if (!toBeDetached.contains(directResource) && !toBeDetached.contains(container)) { @@ -2432,7 +2428,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa super.doActivate(); InternalCDOSession session = getSession(); - if (session.getRepositoryInfo().getIDGenerationLocation() == IDGenerationLocation.STORE) + if (session.getRepositoryInfo().getIDGenerationLocation() == CDOCommonRepository.IDGenerationLocation.STORE) { idGenerator = new TempIDGenerator(); } @@ -2492,7 +2488,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } Map<CDOObject, Pair<CDORevision, CDORevisionDelta>> conflicts = // - super.invalidate(allChangedObjects, allDetachedObjects, deltas, revisionDeltas, detachedObjects); + super.invalidate(allChangedObjects, allDetachedObjects, deltas, revisionDeltas, detachedObjects); if (!allChangedObjects.isEmpty()) { @@ -2524,7 +2520,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - Internal eDirectResource = referencerInternalEObject.eDirectResource(); + Resource.Internal eDirectResource = referencerInternalEObject.eDirectResource(); if (eDirectResource instanceof CDOResource) { CDOObject cdoResource = (CDOObject)eDirectResource; @@ -2555,13 +2551,15 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private void removeCrossReferences(Collection<CDOObject> possibleTargets, Collection<CDOObject> referencers) { - List<Pair<Setting, EObject>> objectsToBeRemoved = new LinkedList<Pair<Setting, EObject>>(); + CDOStaleReferenceCleaner staleReferenceCleaner = options().getStaleReferenceCleaner(); + Collection<Pair<EStructuralFeature.Setting, EObject>> staleReferencesToClean = new LinkedList<Pair<EStructuralFeature.Setting, EObject>>(); + for (CDOObject referencer : referencers) { InternalCDOObject internalReferencer = (InternalCDOObject)referencer; InternalCDOClassInfo referencerClassInfo = internalReferencer.cdoClassInfo(); - FeatureIterator<EObject> it = getChangeableCrossReferences(referencer); + EContentsEList.FeatureIterator<EObject> it = getChangeableCrossReferences(referencer); while (it.hasNext()) { EObject referencedObject = it.next(); @@ -2604,21 +2602,23 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - Setting setting = internalReferencer.eSetting(reference); - objectsToBeRemoved.add(Pair.create(setting, referencedObject)); + EStructuralFeature.Setting setting = internalReferencer.eSetting(reference); + staleReferencesToClean.add(Pair.create(setting, referencedObject)); } } } - for (Pair<Setting, EObject> pair : objectsToBeRemoved) + if (!staleReferencesToClean.isEmpty()) { - EcoreUtil.remove(pair.getElement1(), pair.getElement2()); + staleReferenceCleaner.cleanStaleReferences(staleReferencesToClean); } } - private FeatureIterator<EObject> getChangeableCrossReferences(EObject object) + private EContentsEList.FeatureIterator<EObject> getChangeableCrossReferences(EObject object) { - FeatureSubsetSupplier features = (FeatureSubsetSupplier)object.eClass().getEAllStructuralFeatures(); + EClassImpl.FeatureSubsetSupplier features = (EClassImpl.FeatureSubsetSupplier)object.eClass() + .getEAllStructuralFeatures(); + EStructuralFeature[] crossReferences = features.crossReferences(); if (crossReferences != null) { @@ -2650,7 +2650,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } } - return (FeatureIterator<EObject>)ECrossReferenceEList.<EObject> emptyContentsEList().iterator(); + return (EContentsEList.FeatureIterator<EObject>)ECrossReferenceEList.<EObject> emptyContentsEList().iterator(); } public synchronized long getLastCommitTime() @@ -2719,7 +2719,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa } @Override - protected InternalCDOLockState createUpdatedLockStateForNewObject(CDOObject object, LockType lockType, boolean on) + protected InternalCDOLockState createUpdatedLockStateForNewObject(CDOObject object, IRWLockManager.LockType lockType, + boolean on) { CheckUtil.checkState(FSMUtil.isNew(object), "Object is not in NEW state"); CheckUtil.checkArg(lockType, "lockType"); @@ -2825,8 +2826,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa SyntheticCDORevision[] synthetics = new SyntheticCDORevision[1]; InternalCDORevisionManager revisionManager = transaction.getSession().getRevisionManager(); - InternalCDORevision result = // - revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, CDORevision.DEPTH_NONE, true, synthetics); + InternalCDORevision result = revisionManager.getRevision(id, transaction, CDORevision.UNCHUNKED, + CDORevision.DEPTH_NONE, true, synthetics); if (result != null) { @@ -3191,7 +3192,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa if (result.getRollbackMessage() != null) { CDOCommitInfo commitInfo = new FailureCommitInfo(timeStamp, result.getPreviousTimeStamp()); - session.invalidate(commitInfo, transaction, clearResourcePathCache, CommitNotificationInfo.IMPACT_NONE, null); + session.invalidate(commitInfo, transaction, clearResourcePathCache, + CDOProtocol.CommitNotificationInfo.IMPACT_NONE, null); return; } @@ -3289,7 +3291,7 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa CDOLockState[] newLockStates = result.getNewLockStates(); if (newLockStates != null) { - updateAndNotifyLockStates(Operation.UNLOCK, null, result.getTimeStamp(), newLockStates); + updateAndNotifyLockStates(CDOLockChangeInfo.Operation.UNLOCK, null, result.getTimeStamp(), newLockStates); } } catch (RuntimeException ex) @@ -3475,6 +3477,8 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa private List<CDOConflictResolver> conflictResolvers = new ArrayList<CDOConflictResolver>(); + private CDOStaleReferenceCleaner staleReferenceCleaner = CDOStaleReferenceCleaner.DEFAULT; + private boolean autoReleaseLocksEnabled = true; public OptionsImpl() @@ -3577,6 +3581,33 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa fireEvent(event); } + public CDOStaleReferenceCleaner getStaleReferenceCleaner() + { + return staleReferenceCleaner; + } + + public void setStaleReferenceCleaner(CDOStaleReferenceCleaner staleReferenceCleaner) + { + checkActive(); + + if (staleReferenceCleaner == null) + { + staleReferenceCleaner = CDOStaleReferenceCleaner.DEFAULT; + } + + IEvent event = null; + synchronized (CDOTransactionImpl.this) + { + if (this.staleReferenceCleaner != staleReferenceCleaner) + { + this.staleReferenceCleaner = staleReferenceCleaner; + event = new StaleReferenceCleanerEventImpl(); + } + } + + fireEvent(event); + } + public void disposeConflictResolvers() { try @@ -3660,6 +3691,19 @@ public class CDOTransactionImpl extends CDOViewImpl implements InternalCDOTransa /** * @author Eike Stepper */ + private final class StaleReferenceCleanerEventImpl extends OptionsEvent implements StaleReferenceCleanerEvent + { + private static final long serialVersionUID = 1L; + + public StaleReferenceCleanerEventImpl() + { + super(OptionsImpl.this); + } + } + + /** + * @author Eike Stepper + */ private final class AutoReleaseLocksEventImpl extends OptionsEvent implements AutoReleaseLocksEvent { private static final long serialVersionUID = 1L; |