diff options
-rw-r--r-- | plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java | 4 | ||||
-rw-r--r-- | plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationNotification.java (renamed from plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationRequest.java) | 6 | ||||
-rw-r--r-- | plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java | 117 | ||||
-rw-r--r-- | plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java | 75 |
4 files changed, 128 insertions, 74 deletions
diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java index 771bc767e5..f295a5eaa0 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/Session.java @@ -18,7 +18,7 @@ import org.eclipse.emf.cdo.internal.protocol.revision.CDOIDProvider; import org.eclipse.emf.cdo.internal.protocol.revision.CDORevisionImpl; import org.eclipse.emf.cdo.internal.server.bundle.OM; import org.eclipse.emf.cdo.internal.server.protocol.CDOServerProtocol; -import org.eclipse.emf.cdo.internal.server.protocol.InvalidationRequest; +import org.eclipse.emf.cdo.internal.server.protocol.InvalidationNotification; import org.eclipse.emf.cdo.protocol.CDOID; import org.eclipse.emf.cdo.protocol.CDOProtocolConstants; import org.eclipse.emf.cdo.protocol.model.CDOClassRef; @@ -164,7 +164,7 @@ public class Session extends Container<IView> implements ISession, CDOIDProvider { try { - new InvalidationRequest(protocol.getChannel(), timeStamp, dirtyIDs).send(); + new InvalidationNotification(protocol.getChannel(), timeStamp, dirtyIDs).send(); } catch (Exception ex) { diff --git a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationRequest.java b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationNotification.java index b0b2085c19..59d41e11d6 100644 --- a/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationRequest.java +++ b/plugins/org.eclipse.emf.cdo.server/src/org/eclipse/emf/cdo/internal/server/protocol/InvalidationNotification.java @@ -26,15 +26,15 @@ import java.io.IOException; /** * @author Eike Stepper */ -public class InvalidationRequest extends Request +public class InvalidationNotification extends Request { - private static final ContextTracer PROTOCOL = new ContextTracer(OM.DEBUG_PROTOCOL, InvalidationRequest.class); + private static final ContextTracer PROTOCOL = new ContextTracer(OM.DEBUG_PROTOCOL, InvalidationNotification.class); private long timeStamp; private CDOID[] dirtyIDs; - public InvalidationRequest(IChannel channel, long timeStamp, CDOID[] dirtyIDs) + public InvalidationNotification(IChannel channel, long timeStamp, CDOID[] dirtyIDs) { super(channel); this.timeStamp = timeStamp; diff --git a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java index 8699112335..485ad40cdf 100644 --- a/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java +++ b/plugins/org.eclipse.emf.cdo/src/org/eclipse/emf/internal/cdo/CDOViewImpl.java @@ -102,7 +102,7 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier protected ConcurrentMap<CDOID, InternalCDOObject> createObjectsMap() { - return new ReferenceValueMap.Soft<CDOID, InternalCDOObject>(); + return new ReferenceValueMap.Weak<CDOID, InternalCDOObject>(); } public int getViewID() @@ -271,39 +271,47 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier } lastLookupID = id; - lastLookupObject = objects.get(id); - if (lastLookupObject == null) + synchronized (objects) { - if (id.isMeta()) + lastLookupObject = objects.get(id); + if (lastLookupObject == null) { - lastLookupObject = createMetaObject(id); - } - else - { - if (loadOnDemand) + if (id.isMeta()) { - lastLookupObject = createObject(id); + lastLookupObject = createMetaObject(id); } else { - lastLookupObject = createProxy(id); + if (loadOnDemand) + { + lastLookupObject = createObject(id); + } + else + { + lastLookupObject = createProxy(id); + } } - } - registerObject(lastLookupObject); + registerObject(lastLookupObject); + } } - return lastLookupObject; } public boolean isObjectRegistered(CDOID id) { - return objects.containsKey(id); + synchronized (objects) + { + return objects.containsKey(id); + } } public InternalCDOObject removeObject(CDOID id) { - return objects.remove(id); + synchronized (objects) + { + return objects.remove(id); + } } /** @@ -475,7 +483,12 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier TRACER.format("Registering {0}", object); } - InternalCDOObject old = objects.put(object.cdoID(), object); + InternalCDOObject old; + synchronized (objects) + { + old = objects.put(object.cdoID(), object); + } + if (old != null) { throw new IllegalStateException("Duplicate ID: " + object); @@ -489,7 +502,12 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier TRACER.format("Deregistering {0}", object); } - InternalCDOObject old = objects.remove(object.cdoID()); + InternalCDOObject old; + synchronized (objects) + { + old = objects.remove(object.cdoID()); + } + if (old == null) { throw new IllegalStateException("Unknown ID: " + object); @@ -498,47 +516,20 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier public void remapObject(CDOID oldID) { - InternalCDOObject object = objects.remove(oldID); - CDOID newID = object.cdoID(); - objects.put(newID, object); + CDOID newID; + synchronized (objects) + { + InternalCDOObject object = objects.remove(oldID); + newID = object.cdoID(); + objects.put(newID, object); + } + if (TRACER.isEnabled()) { TRACER.format("Remapping {0} --> {1}", oldID, newID); } } - // public final class HistoryEntryImpl implements HistoryEntry, Comparable - // { - // private String resourcePath; - // - // private HistoryEntryImpl(String resourcePath) - // { - // this.resourcePath = resourcePath; - // } - // - // public CDOView getView() - // { - // return CDOViewImpl.this; - // } - // - // public String getResourcePath() - // { - // return resourcePath; - // } - // - // public int compareTo(Object o) - // { - // HistoryEntry that = (HistoryEntry)o; - // return resourcePath.compareTo(that.getResourcePath()); - // } - // - // @Override - // public String toString() - // { - // return resourcePath; - // } - // } - /** * Turns registered objects into proxies and synchronously delivers invalidation events to registered event listeners. * <p> @@ -558,15 +549,20 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier List<InternalCDOObject> dirtyObjects = enableInvalidationNotifications ? new ArrayList<InternalCDOObject>() : null; for (CDOID dirtyOID : dirtyOIDs) { - InternalCDOObject dirtyObject = objects.get(dirtyOID); - if (dirtyObject != null) + InternalCDOObject dirtyObject; + synchronized (objects) { - CDOStateMachine.INSTANCE.invalidate(dirtyObject, timeStamp); - if (dirtyObjects != null && dirtyObject.eNotificationRequired()) + dirtyObject = objects.get(dirtyOID); + if (dirtyObject != null) { - dirtyObjects.add(dirtyObject); + CDOStateMachine.INSTANCE.invalidate(dirtyObject, timeStamp); } } + + if (dirtyObject != null && dirtyObjects != null && dirtyObject.eNotificationRequired()) + { + dirtyObjects.add(dirtyObject); + } } if (dirtyObjects != null) @@ -595,7 +591,10 @@ public class CDOViewImpl extends org.eclipse.net4j.internal.util.event.Notifier } else { - internalObjects = this.objects.values(); + synchronized (objects) + { + internalObjects = new ArrayList<InternalCDOObject>(this.objects.values()); + } } int result = internalObjects.size(); diff --git a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java index dc605dd1cc..d9fd2ed293 100644 --- a/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java +++ b/plugins/org.eclipse.net4j.util/src/org/eclipse/net4j/util/ref/ReferenceValueMap.java @@ -10,7 +10,6 @@ **************************************************************************/ package org.eclipse.net4j.util.ref; -import org.eclipse.net4j.util.ObjectUtil; import org.eclipse.net4j.util.collection.MapEntry; import java.lang.ref.ReferenceQueue; @@ -18,11 +17,22 @@ import java.util.AbstractMap; import java.util.AbstractSet; import java.util.Iterator; import java.util.Map; +import java.util.NoSuchElementException; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; /** + * A {@link ConcurrentMap} implementation that uses {@link KeyedReference} instances ({@link KeyedReference#Strong Strong}, + * {@link KeyedReference#Soft Soft}, {@link KeyedReference#Weak Weak} or {@link KeyedReference#Phantom Phantom}) as + * its values. + * <p> + * A <code>ReferenceValueMap</code> can be used to cache mappings until the <em>value</em> of the mapping is no + * longer reachable from outside of the map + * <p> + * <b>Note:</b> This map is not synchronized. If it is to be used by multiple threads concurrently the user is + * responsible for applying proper external synchronization! + * * @author Eike Stepper */ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implements ConcurrentMap<K, V> @@ -69,9 +79,9 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen KeyedReference<K, V> ref = map.get(key); if (ref != null) { - if (ref.isEnqueued()) + if (ref.get() == null) { - map.remove(key); + ref.enqueue(); return false; } @@ -91,7 +101,14 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen for (KeyedReference<K, V> ref : map.values()) { - if (!ref.isEnqueued() && ObjectUtil.equals(value, dereference(ref))) + V v = ref.get(); + if (v == null) + { + ref.enqueue(); + return false; + } + + if (value.equals(v)) { return true; } @@ -221,7 +238,13 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen return null; } - return ref.get(); + V value = ref.get(); + if (value == null) + { + ref.enqueue(); + } + + return value; } protected abstract KeyedReference<K, V> createReference(K key, V value, ReferenceQueue<V> queue); @@ -413,6 +436,8 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen { private Iterator<Entry<K, KeyedReference<K, V>>> it = map.entrySet().iterator(); + private MapEntry<K, V> nextEntry; + private K lastKey; public EntrySetIterator() @@ -421,15 +446,44 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen public boolean hasNext() { - return it.hasNext(); + if (nextEntry != null) + { + return true; + } + + while (it.hasNext()) + { + Entry<K, KeyedReference<K, V>> entry = it.next(); + lastKey = entry.getKey(); + V value = dereference(entry.getValue()); + if (value != null) + { + nextEntry = new MapEntry<K, V>(lastKey, value); + return true; + } + } + + return false; } public Entry<K, V> next() { - Entry<K, KeyedReference<K, V>> entry = it.next(); - lastKey = entry.getKey(); - V value = dereference(entry.getValue()); - return new MapEntry<K, V>(lastKey, value); + if (nextEntry == null) + { + if (!hasNext()) + { + throw new NoSuchElementException(); + } + } + + try + { + return nextEntry; + } + finally + { + nextEntry = null; + } } public void remove() @@ -441,6 +495,7 @@ public abstract class ReferenceValueMap<K, V> extends AbstractMap<K, V> implemen map.remove(lastKey); lastKey = null; + nextEntry = null; } } } |