From 27d9fe36b46524b7d285fd53a416f510c9224263 Mon Sep 17 00:00:00 2001 From: Eike Stepper Date: Tue, 13 Dec 2016 11:50:32 +0100 Subject: [509141] Provide CDORegistrationHandler callbacks https://bugs.eclipse.org/bugs/show_bug.cgi?id=509141--- .../src/org/eclipse/emf/cdo/CDOAdapter.java | 4 +- .../src/org/eclipse/emf/cdo/CDOLocalAdapter.java | 24 +++ .../CDOPostEventTransactionHandler.java | 19 ++- .../emf/cdo/transaction/CDOPushTransaction.java | 25 +++ .../emf/cdo/view/CDORegistrationHandler.java | 156 ++++++++++++++++++ .../src/org/eclipse/emf/cdo/view/CDOView.java | 15 ++ .../emf/internal/cdo/view/AbstractCDOView.java | 181 ++++++++++++++++++--- .../eclipse/emf/internal/cdo/view/CDOViewImpl.java | 10 +- .../eclipse/net4j/util/tests/AbstractOMTest.java | 24 +++ .../eclipse/net4j/util/ref/ReferenceValueMap2.java | 17 +- 10 files changed, 440 insertions(+), 35 deletions(-) create mode 100644 plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLocalAdapter.java create mode 100644 plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDORegistrationHandler.java (limited to 'plugins') diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOAdapter.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOAdapter.java index 1f12acb231..987bc9a8b3 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOAdapter.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOAdapter.java @@ -18,12 +18,12 @@ import org.eclipse.emf.cdo.view.CDOView.Options; import org.eclipse.emf.common.notify.Adapter; /** - * A marker interface for {@link Adapter adpters} to indicate that change subscriptions should be registered with the + * A marker interface for {@link Adapter adapters} to indicate that change subscriptions should be registered with the * repository if they are attached to {@link CDOObject objects}. *

* This special marker interface is intended to be used with {@link CDOAdapterPolicy#CDO}. Note that you can also define * your own {@link CDOAdapterPolicy adapter policy} and {@link Options#addChangeSubscriptionPolicy(CDOAdapterPolicy) - * register} it with the {@link CDOView view} to make your own adapters trigger change subscription. + * register} it with the {@link CDOView view} to make your own adapters trigger change subscriptions. * * @author Simon McDuff * @since 2.0 diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLocalAdapter.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLocalAdapter.java new file mode 100644 index 0000000000..ac7e4240b4 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/CDOLocalAdapter.java @@ -0,0 +1,24 @@ +/* + * 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; + +import org.eclipse.emf.common.notify.Adapter; + +/** + * A marker interface for {@link Adapter adapters} to indicate that change subscriptions should not be registered with the + * repository if they are attached to {@link CDOObject objects}. + * + * @author Eike Stepper + * @since 4.6 + */ +public interface CDOLocalAdapter extends Adapter +{ +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPostEventTransactionHandler.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPostEventTransactionHandler.java index b33a634806..616de0231c 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPostEventTransactionHandler.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPostEventTransactionHandler.java @@ -144,23 +144,32 @@ public abstract class CDOPostEventTransactionHandler implements CDOTransactionHa { postEvent((CDOTransaction)object.cdoView(), object, msg); - boolean eDeliver = object.eDeliver(); + boolean deliver = object.eDeliver(); try { - object.eSetDeliver(false); + if (deliver) + { + object.eSetDeliver(false); + } + adapters.remove(this); } finally { - object.eSetDeliver(eDeliver); + if (deliver) + { + object.eSetDeliver(true); + } } } } } } - private boolean isModifyingEvent(int eventType) + protected abstract void postEvent(CDOTransaction transaction, CDOObject object, Notification msg); + + private static boolean isModifyingEvent(int eventType) { switch (eventType) { @@ -177,7 +186,5 @@ public abstract class CDOPostEventTransactionHandler implements CDOTransactionHa return false; } } - - protected abstract void postEvent(CDOTransaction transaction, CDOObject object, Notification msg); } } diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java index 70f82c7eef..c68dc5e2ee 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/transaction/CDOPushTransaction.java @@ -33,6 +33,7 @@ import org.eclipse.emf.cdo.session.CDOSession; import org.eclipse.emf.cdo.util.CommitException; import org.eclipse.emf.cdo.view.CDOObjectHandler; import org.eclipse.emf.cdo.view.CDOQuery; +import org.eclipse.emf.cdo.view.CDORegistrationHandler; import org.eclipse.emf.cdo.view.CDOUnitManager; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewProvider; @@ -329,6 +330,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction delegate.addObjectHandler(handler); } + /** + * @since 4.6 + */ + public void addRegistrationHandler(CDORegistrationHandler handler) + { + delegate.addRegistrationHandler(handler); + } + /** * @since 4.0 */ @@ -491,6 +500,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction return delegate.getObjectHandlers(); } + /** + * @since 4.6 + */ + public CDORegistrationHandler[] getRegistrationHandlers() + { + return delegate.getRegistrationHandlers(); + } + public CDOResource getOrCreateResource(String path) { return delegate.getOrCreateResource(path); @@ -817,6 +834,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction delegate.removeObjectHandler(handler); } + /** + * @since 4.6 + */ + public void removeRegistrationHandler(CDORegistrationHandler handler) + { + delegate.removeRegistrationHandler(handler); + } + /** * @since 4.0 */ diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDORegistrationHandler.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDORegistrationHandler.java new file mode 100644 index 0000000000..743f585ae9 --- /dev/null +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDORegistrationHandler.java @@ -0,0 +1,156 @@ +/* + * 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.view; + +import org.eclipse.emf.cdo.CDOObject; +import org.eclipse.emf.cdo.common.id.CDOID; + +import org.eclipse.net4j.util.event.IListener; +import org.eclipse.net4j.util.lifecycle.ILifecycle; +import org.eclipse.net4j.util.lifecycle.LifecycleEventAdapter; +import org.eclipse.net4j.util.lifecycle.LifecycleUtil; + +import org.eclipse.emf.spi.cdo.InternalCDOObject; +import org.eclipse.emf.spi.cdo.InternalCDOView; + +/** + * Call-back handler used by {@link CDOView views} to tell implementors of this interface about registrations and deregistrations + * of {@link CDOObject objects} with {@link CDOView views}. + * + * @author Eike Stepper + * @since 4.6 + * @see CDOView#addRegistrationHandler(CDORegistrationHandler) + * @see CDOView#removeRegistrationHandler(CDORegistrationHandler) + * @see CDOView#isObjectRegistered(org.eclipse.emf.cdo.common.id.CDOID) + */ +public interface CDORegistrationHandler +{ + public void objectRegistered(CDOView view, CDOObject object); + + public void objectDeregistered(CDOView view, CDOObject object); + + public void objectCollected(CDOView view, CDOID id); + + /** + * @author Eike Stepper + */ + public static class Default implements CDORegistrationHandler + { + private final IListener deactivateListener = new LifecycleEventAdapter() + { + @Override + protected void onDeactivated(ILifecycle lifecycle) + { + dispose(); + } + }; + + private CDOView view; + + public Default(final CDOView view) + { + view.syncExec(new Runnable() + { + public void run() + { + doInitialize(view); + } + }); + + this.view = view; + } + + public final CDOView getView() + { + return view; + } + + public final boolean isDisposed() + { + return view == null; + } + + public synchronized void dispose() + { + if (view != null) + { + final CDOView finalView = view; + view = null; + + finalView.syncExec(new Runnable() + { + public void run() + { + doDispose(finalView); + } + }); + } + } + + /** + * Called by the view for each registered object. + *

+ * Also called during initialization for already loaded objects; + * {@link #isDisposed()} returns true in these cases. + */ + public void objectRegistered(CDOView view, CDOObject object) + { + // Subclasses may override. + } + + /** + * Called by the view for each deregistered object. + *

+ * Also called during dispose for already loaded objects; + * {@link #isDisposed()} returns true in these cases. + */ + public void objectDeregistered(CDOView view, CDOObject object) + { + // Subclasses may override. + } + + /** + * Called by the view for each garbage-collected object. + */ + public void objectCollected(CDOView view, CDOID id) + { + // Subclasses may override. + } + + protected void doInitialize(CDOView view) + { + if (LifecycleUtil.isActive(view)) + { + for (InternalCDOObject object : ((InternalCDOView)view).getObjects().values()) + { + objectRegistered(view, object); + } + } + + view.addRegistrationHandler(this); + view.addListener(deactivateListener); + } + + protected void doDispose(CDOView view) + { + view.removeListener(deactivateListener); + view.removeRegistrationHandler(this); + + if (LifecycleUtil.isActive(view)) + { + for (InternalCDOObject object : ((InternalCDOView)view).getObjects().values()) + { + objectDeregistered(view, object); + } + } + } + } +} diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java index 98c1a0d89d..d13a555836 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/cdo/view/CDOView.java @@ -564,6 +564,21 @@ public interface CDOView extends CDOCommonView, CDOUpdatable, CDOCommitHistory.P */ public CDOObjectHandler[] getObjectHandlers(); + /** + * @since 4.6 + */ + public void addRegistrationHandler(CDORegistrationHandler handler); + + /** + * @since 4.6 + */ + public void removeRegistrationHandler(CDORegistrationHandler handler); + + /** + * @since 4.6 + */ + public CDORegistrationHandler[] getRegistrationHandlers(); + /** * Same as createQuery(language, queryString, null). * diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java index c502eaae3d..5562d069da 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/AbstractCDOView.java @@ -66,6 +66,7 @@ import org.eclipse.emf.cdo.util.ReadOnlyException; import org.eclipse.emf.cdo.view.CDOAdapterPolicy; import org.eclipse.emf.cdo.view.CDOObjectHandler; import org.eclipse.emf.cdo.view.CDOQuery; +import org.eclipse.emf.cdo.view.CDORegistrationHandler; import org.eclipse.emf.cdo.view.CDOView; import org.eclipse.emf.cdo.view.CDOViewAdaptersNotifiedEvent; import org.eclipse.emf.cdo.view.CDOViewEvent; @@ -81,6 +82,7 @@ import org.eclipse.emf.internal.cdo.transaction.CDOTransactionImpl; import org.eclipse.net4j.util.AdapterUtil; import org.eclipse.net4j.util.CheckUtil; import org.eclipse.net4j.util.ImplementationError; +import org.eclipse.net4j.util.ReflectUtil; import org.eclipse.net4j.util.ReflectUtil.ExcludeFromDump; import org.eclipse.net4j.util.StringUtil; import org.eclipse.net4j.util.WrappedException; @@ -127,6 +129,7 @@ import org.eclipse.emf.spi.cdo.InternalCDOViewSet; import org.eclipse.core.runtime.IProgressMonitor; import java.io.IOException; +import java.lang.reflect.Method; import java.text.MessageFormat; import java.util.ArrayList; import java.util.Collection; @@ -186,6 +189,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl registrationHandlers = new ConcurrentArray() + { + @Override + protected CDORegistrationHandler[] newArray(int length) + { + return new CDORegistrationHandler[length]; + } + }; + private final IRegistry properties = new HashMapRegistry() { @Override @@ -294,6 +306,18 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl map = (ReferenceValueMap2)objects; + Method method = ReflectUtil.getMethod(ReferenceValueMap2.class, "internalPurgeQueue"); + return (Integer)ReflectUtil.invokeMethod(method, map); + } + + return 0; + } + public Map getObjects() { synchronized (getViewMonitor()) @@ -347,7 +371,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Strong(map); + newObjects = new ReferenceValueMap2.Strong(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -359,7 +391,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Soft(map); + newObjects = new ReferenceValueMap2.Soft(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -371,7 +411,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Weak(map); + newObjects = new ReferenceValueMap2.Weak(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -1948,11 +1996,6 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImplnull */ @@ -2432,11 +2475,6 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl ids) @@ -1379,7 +1382,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv } } - getChangeSubscriptionManager().handleDetachedObjects(detachedObjects); + changeSubscriptionManager.handleDetachedObjects(detachedObjects); } } finally @@ -2529,6 +2532,11 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv private boolean shouldSubscribe(EObject eObject, Adapter adapter) { + if (adapter instanceof CDOLocalAdapter) + { + return false; + } + if (unitManager.getOpenUnitUnsynced(eObject) != null) { return false; diff --git a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java index 33a1b5eafc..b056bee2e9 100644 --- a/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java +++ b/plugins/org.eclipse.net4j.tests/src/org/eclipse/net4j/util/tests/AbstractOMTest.java @@ -768,6 +768,30 @@ public abstract class AbstractOMTest extends TestCase skipTest(true); } + public static void triggerGC() + { + List bigdata = new ArrayList(); + + try + { + while (true) + { + try + { + bigdata.add(new byte[1024 * 1024]); + } + catch (Throwable ex) + { + break; + } + } + } + catch (Throwable ex) + { + //$FALL-THROUGH$ + } + } + public static void disableLog4j() { BasicConfigurator.configure(new Appender() diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java index 2f95a4c97c..6d934c6f50 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap2.java @@ -169,19 +169,34 @@ public abstract class ReferenceValueMap2 extends AbstractMap return new ReferenceQueue(); } + /** + * @since 3.7 + */ @SuppressWarnings("unchecked") - protected void purgeQueue() + protected int internalPurgeQueue() { if (queue != null) { + int purged = 0; KeyedReference ref; + while ((ref = (KeyedReference)queue.poll()) != null) { K key = ref.getKey(); map.remove(key); purged(key); + ++purged; } + + return purged; } + + return 0; + } + + protected void purgeQueue() + { + internalPurgeQueue(); } protected void purged(K key) -- cgit v1.2.1