diff options
author | Eike Stepper | 2016-12-13 10:50:32 +0000 |
---|---|---|
committer | Eike Stepper | 2016-12-13 10:50:32 +0000 |
commit | 27d9fe36b46524b7d285fd53a416f510c9224263 (patch) | |
tree | 38ed6851f9452e88366c667043e8d3153d21771d | |
parent | 7b509f423332eb4199e3a07b3e13f0ece39d50a9 (diff) | |
download | cdo-27d9fe36b46524b7d285fd53a416f510c9224263.tar.gz cdo-27d9fe36b46524b7d285fd53a416f510c9224263.tar.xz cdo-27d9fe36b46524b7d285fd53a416f510c9224263.zip |
[509141] Provide CDORegistrationHandler callbacks
https://bugs.eclipse.org/bugs/show_bug.cgi?id=509141
10 files changed, 440 insertions, 35 deletions
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}. * <p> * 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 <b>not</b> 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; @@ -330,6 +331,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction } /** + * @since 4.6 + */ + public void addRegistrationHandler(CDORegistrationHandler handler) + { + delegate.addRegistrationHandler(handler); + } + + /** * @since 4.0 */ public void addTransactionHandler(CDOTransactionHandlerBase handler) @@ -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); @@ -818,6 +835,14 @@ public class CDOPushTransaction extends Notifier implements CDOTransaction } /** + * @since 4.6 + */ + public void removeRegistrationHandler(CDORegistrationHandler handler) + { + delegate.removeRegistrationHandler(handler); + } + + /** * @since 4.0 */ public void removeTransactionHandler(CDOTransactionHandlerBase handler) 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. + * <p> + * Also called during initialization for already loaded objects; + * {@link #isDisposed()} returns <code>true</code> in these cases. + */ + public void objectRegistered(CDOView view, CDOObject object) + { + // Subclasses may override. + } + + /** + * Called by the view for each deregistered object. + * <p> + * Also called during dispose for already loaded objects; + * {@link #isDisposed()} returns <code>true</code> 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 @@ -565,6 +565,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 <code>createQuery(language, queryString, null)</code>. * * @see #createQuery(String, String, Object) 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<CDOOb } }; + private final ConcurrentArray<CDORegistrationHandler> registrationHandlers = new ConcurrentArray<CDORegistrationHandler>() + { + @Override + protected CDORegistrationHandler[] newArray(int length) + { + return new CDORegistrationHandler[length]; + } + }; + private final IRegistry<String, Object> properties = new HashMapRegistry<String, Object>() { @Override @@ -294,6 +306,18 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } + public int purgeUnusedObjects() + { + if (objects instanceof ReferenceValueMap2) + { + ReferenceValueMap2<CDOID, InternalCDOObject> map = (ReferenceValueMap2<CDOID, InternalCDOObject>)objects; + Method method = ReflectUtil.getMethod(ReferenceValueMap2.class, "internalPurgeQueue"); + return (Integer)ReflectUtil.invokeMethod(method, map); + } + + return 0; + } + public Map<CDOID, InternalCDOObject> getObjects() { synchronized (getViewMonitor()) @@ -347,7 +371,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Strong<CDOID, InternalCDOObject>(map); + newObjects = new ReferenceValueMap2.Strong<CDOID, InternalCDOObject>(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -359,7 +391,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Soft<CDOID, InternalCDOObject>(map); + newObjects = new ReferenceValueMap2.Soft<CDOID, InternalCDOObject>(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -371,7 +411,15 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } Map<CDOID, KeyedReference<CDOID, InternalCDOObject>> map = CDOIDUtil.createMap(); - newObjects = new ReferenceValueMap2.Weak<CDOID, InternalCDOObject>(map); + newObjects = new ReferenceValueMap2.Weak<CDOID, InternalCDOObject>(map) + { + @Override + protected void purged(CDOID id) + { + objectCollected(id); + } + }; + break; } @@ -1948,11 +1996,6 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } - protected void objectDeregistered(InternalCDOObject object) - { - // Subclasses may override. - } - /** * @return Never <code>null</code> */ @@ -2432,11 +2475,6 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } - protected void objectRegistered(InternalCDOObject object) - { - // Subclasses may override. - } - public void deregisterObject(InternalCDOObject object) { synchronized (getViewMonitor()) @@ -2459,6 +2497,81 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb } } + protected void objectRegistered(InternalCDOObject object) + { + CDORegistrationHandler[] handlers = getRegistrationHandlers(); + if (handlers.length != 0) + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (int i = 0; i < handlers.length; i++) + { + CDORegistrationHandler handler = handlers[i]; + handler.objectRegistered(this, object); + } + } + finally + { + unlockView(); + } + } + } + } + + protected void objectDeregistered(InternalCDOObject object) + { + CDORegistrationHandler[] handlers = getRegistrationHandlers(); + if (handlers.length != 0) + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (int i = 0; i < handlers.length; i++) + { + CDORegistrationHandler handler = handlers[i]; + handler.objectDeregistered(this, object); + } + } + finally + { + unlockView(); + } + } + } + } + + protected void objectCollected(CDOID id) + { + CDORegistrationHandler[] handlers = getRegistrationHandlers(); + if (handlers.length != 0) + { + synchronized (getViewMonitor()) + { + lockView(); + + try + { + for (int i = 0; i < handlers.length; i++) + { + CDORegistrationHandler handler = handlers[i]; + handler.objectCollected(this, id); + } + } + finally + { + unlockView(); + } + } + } + } + public void remapObject(CDOID oldID) { synchronized (getViewMonitor()) @@ -2508,26 +2621,44 @@ public abstract class AbstractCDOView extends CDOCommitHistoryProviderImpl<CDOOb public void handleObjectStateChanged(InternalCDOObject object, CDOState oldState, CDOState newState) { - synchronized (getViewMonitor()) + CDOObjectHandler[] handlers = getObjectHandlers(); + if (handlers.length != 0) { - lockView(); - - try + synchronized (getViewMonitor()) { - CDOObjectHandler[] handlers = getObjectHandlers(); - for (int i = 0; i < handlers.length; i++) + lockView(); + + try { - CDOObjectHandler handler = handlers[i]; - handler.objectStateChanged(this, object, oldState, newState); + for (int i = 0; i < handlers.length; i++) + { + CDOObjectHandler handler = handlers[i]; + handler.objectStateChanged(this, object, oldState, newState); + } + } + finally + { + unlockView(); } - } - finally - { - unlockView(); } } } + public void addRegistrationHandler(CDORegistrationHandler handler) + { + registrationHandlers.add(handler); + } + + public void removeRegistrationHandler(CDORegistrationHandler handler) + { + registrationHandlers.remove(handler); + } + + public CDORegistrationHandler[] getRegistrationHandlers() + { + return registrationHandlers.get(); + } + /* * Synchronized through InvalidationRunner.run() */ diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java index 601aa997a0..b68084b1d8 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/view/CDOViewImpl.java @@ -12,6 +12,7 @@ */ package org.eclipse.emf.internal.cdo.view; +import org.eclipse.emf.cdo.CDOLocalAdapter; import org.eclipse.emf.cdo.CDONotification; import org.eclipse.emf.cdo.CDOObject; import org.eclipse.emf.cdo.common.CDOCommonView; @@ -970,6 +971,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv @Override protected void objectRegistered(InternalCDOObject object) { + super.objectRegistered(object); unitManager.addObject(object); } @@ -977,6 +979,7 @@ public class CDOViewImpl extends AbstractCDOView implements IExecutorServiceProv protected void objectDeregistered(InternalCDOObject object) { removeLockState(object); + super.objectDeregistered(object); } public CDOLockState[] getLockStates(Collection<CDOID> 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<byte[]> bigdata = new ArrayList<byte[]>(); + + 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<K, V> extends AbstractMap<K, V> return new ReferenceQueue<V>(); } + /** + * @since 3.7 + */ @SuppressWarnings("unchecked") - protected void purgeQueue() + protected int internalPurgeQueue() { if (queue != null) { + int purged = 0; KeyedReference<K, V> ref; + while ((ref = (KeyedReference<K, V>)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) |