diff options
author | Eike Stepper | 2006-11-13 09:29:45 +0000 |
---|---|---|
committer | Eike Stepper | 2006-11-13 09:29:45 +0000 |
commit | 4d9f313de71f04d621ac122b7f50aecee1c530be (patch) | |
tree | 4bb7c1fde2e79c03ca553a22572bdad4dfc4f929 | |
parent | a0e679541a7f435436d3e8636550d3e663c3534d (diff) | |
download | cdo-4d9f313de71f04d621ac122b7f50aecee1c530be.tar.gz cdo-4d9f313de71f04d621ac122b7f50aecee1c530be.tar.xz cdo-4d9f313de71f04d621ac122b7f50aecee1c530be.zip |
Made IRegistry transactional
15 files changed, 273 insertions, 187 deletions
diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/AbstractConnector.java b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/AbstractConnector.java index 479a18a608..70b0d10ecc 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/AbstractConnector.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/AbstractConnector.java @@ -219,7 +219,8 @@ public abstract class AbstractConnector extends AbstractLifecycle implements Con switch (newState) { case DISCONNECTED: - REGISTRY.deregister(connectorID); + REGISTRY.remove(connectorID); + REGISTRY.commit(); if (finishedConnecting != null) { finishedConnecting.countDown(); @@ -250,7 +251,8 @@ public abstract class AbstractConnector extends AbstractLifecycle implements Con case CONNECTED: finishedConnecting.countDown(); // Just in case of suspicion finishedNegotiating.countDown(); - REGISTRY.register(this); + REGISTRY.put(connectorID, this); + REGISTRY.commit(); break; } @@ -484,7 +486,7 @@ public abstract class AbstractConnector extends AbstractLifecycle implements Con return null; } - ProtocolFactory factory = registry.lookup(protocolID); + ProtocolFactory factory = registry.get(protocolID); if (factory == null) { if (TRACER.isEnabled()) diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/ChannelImpl.java b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/ChannelImpl.java index 072009fa0e..ccd41801bd 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/ChannelImpl.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/internal/net4j/transport/ChannelImpl.java @@ -213,7 +213,8 @@ public class ChannelImpl extends AbstractLifecycle implements Channel, BufferPro if (!(this instanceof ControlChannelImpl)) { - Channel.REGISTRY.register(this); + Channel.REGISTRY.put(getID(), this); + Channel.REGISTRY.commit(); } } @@ -222,7 +223,8 @@ public class ChannelImpl extends AbstractLifecycle implements Channel, BufferPro { if (!(this instanceof ControlChannelImpl)) { - Channel.REGISTRY.deregister(getID()); + Channel.REGISTRY.remove(getID()); + Channel.REGISTRY.commit(); } receiveSerializer = null; diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Channel.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Channel.java index f6212c36d1..1bb7395ab5 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Channel.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Channel.java @@ -12,7 +12,6 @@ package org.eclipse.net4j.transport; import org.eclipse.net4j.util.registry.HashMapRegistry; import org.eclipse.net4j.util.registry.IRegistry; -import org.eclipse.net4j.util.registry.IRegistryElement; /** * A bidirectional communications channel for the asynchronous exchange of @@ -26,7 +25,7 @@ import org.eclipse.net4j.util.registry.IRegistryElement; * * @author Eike Stepper */ -public interface Channel extends BufferHandler, IRegistryElement<ChannelID> +public interface Channel extends BufferHandler { public static final IRegistry<ChannelID, Channel> REGISTRY = new HashMapRegistry(); diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Connector.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Connector.java index 2d84c79c24..6426c4a121 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Connector.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/Connector.java @@ -12,7 +12,6 @@ package org.eclipse.net4j.transport; import org.eclipse.net4j.util.registry.HashMapRegistry; import org.eclipse.net4j.util.registry.IRegistry; -import org.eclipse.net4j.util.registry.IRegistryElement; import java.util.concurrent.ExecutorService; @@ -30,7 +29,7 @@ import java.util.concurrent.ExecutorService; * * @author Eike Stepper */ -public interface Connector extends IRegistryElement<Integer> +public interface Connector { public static final IRegistry<Integer, Connector> REGISTRY = new HashMapRegistry(); diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/ProtocolFactory.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/ProtocolFactory.java index 611d4acff9..ece19acfb0 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/ProtocolFactory.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/transport/ProtocolFactory.java @@ -11,7 +11,6 @@ package org.eclipse.net4j.transport; import org.eclipse.net4j.transport.Connector.Type; -import org.eclipse.net4j.util.registry.IRegistryElement; import java.util.Arrays; import java.util.Collections; @@ -21,7 +20,7 @@ import java.util.Set; /** * @author Eike Stepper */ -public interface ProtocolFactory extends IRegistryElement<String> +public interface ProtocolFactory { public static final Set<Type> FOR_CLIENTS = Collections.singleton(Type.CLIENT); diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/Net4jUtil.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/Net4jUtil.java index a911bc5e9e..e4a8c8de15 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/Net4jUtil.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/Net4jUtil.java @@ -120,7 +120,7 @@ public final class Net4jUtil types = ProtocolFactory.SYMMETRIC; } - Collection<Channel> channels = Channel.REGISTRY.getElements(); + Collection<Channel> channels = Channel.REGISTRY.values(); Collection<Channel> result = new ArrayList(channels.size()); for (Channel channel : channels) { diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java index f9b3df66c6..a997c0c565 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractMappingRegistry.java @@ -10,75 +10,50 @@ **************************************************************************/ package org.eclipse.net4j.util.registry; +import java.util.Collection; import java.util.Map; import java.util.Set; /** * @author Eike Stepper */ -public abstract class AbstractMappingRegistry<ID, E extends IRegistryElement<ID>> extends - AbstractRegistry<ID, E> +public abstract class AbstractMappingRegistry<K, V> extends AbstractRegistry<K, V> { public AbstractMappingRegistry() { - this(DEFAULT_RESOLVING); } - public AbstractMappingRegistry(boolean resolving) + @Override + protected V deregister(Object key) { - super(resolving); + return getMap().remove(key); } - public synchronized void register(E element) + @Override + protected V register(K key, V value) { - E oldElement = getMap().put(element.getID(), element); - if (oldElement != null) - { - fireElementDeregistering(oldElement); - } - - fireElementRegistered(element); + return getMap().put(key, value); } - public synchronized void deregister(ID id) + public Set<Entry<K, V>> entrySet() { - E element = getMap().remove(id); - if (element != null) - { - fireElementDeregistering(element); - } + return getMap().entrySet(); } - /** - * Synchronized to support {@link #resolveElement(IRegistryElement)} - */ - public synchronized E lookup(ID id, boolean resolve) + public V get(Object key) { - E element = getMap().get(id); - if (resolve) - { - element = resolveElement(element); - } - - return element; + return getMap().get(key); } - public Set<ID> getElementIDs() + public Set<K> keySet() { return getMap().keySet(); } - @Override - public synchronized void dispose() - { - getMap().clear(); - } - - @Override - protected void replaceElement(ID id, E element) + public Collection<V> values() { - getMap().put(id, element); + return getMap().values(); } - protected abstract Map<ID, E> getMap(); + protected abstract Map<K, V> getMap(); } diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java index 70dad2a858..76499a126c 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/AbstractRegistry.java @@ -11,14 +11,13 @@ package org.eclipse.net4j.util.registry; import org.eclipse.net4j.util.om.trace.ContextTracer; -import org.eclipse.net4j.util.registry.IRegistryElement.Descriptor; -import org.eclipse.net4j.util.registry.IRegistryListener.EventType; import org.eclipse.internal.net4j.bundle.Net4j; import java.util.ArrayList; -import java.util.Collection; +import java.util.Iterator; import java.util.List; +import java.util.Map; import java.util.Queue; import java.util.Set; import java.util.concurrent.ConcurrentLinkedQueue; @@ -26,90 +25,111 @@ import java.util.concurrent.ConcurrentLinkedQueue; /** * @author Eike Stepper */ -public abstract class AbstractRegistry<ID, E extends IRegistryElement<ID>> implements - IRegistry<ID, E> +public abstract class AbstractRegistry<K, V> implements IRegistry<K, V> { - public static final boolean DEFAULT_RESOLVING = true; - private static final ContextTracer TRACER = new ContextTracer(Net4j.DEBUG_REGISTRY, AbstractRegistry.class); - private boolean resolving; - /** * Don't initialize lazily to circumvent synchronization! */ private Queue<IRegistryListener> listeners = new ConcurrentLinkedQueue(); + private Transaction transaction; + + private Object transactionLock = new Object(); + protected AbstractRegistry() { - this(DEFAULT_RESOLVING); } - public AbstractRegistry(boolean resolving) + public void addRegistryListener(IRegistryListener<K, V> listener) { - setResolving(resolving); + listeners.add(listener); } - public void setResolving(boolean resolving) + public void removeRegistryListener(IRegistryListener<K, V> listener) { - this.resolving = resolving; + listeners.remove(listener); } - public final boolean isResolving() + public void clear() { - return resolving; + Set<K> keys = keySet(); + for (K key : keys) + { + deregister(key); + } } - public final boolean isResolved(ID id) + public boolean containsKey(Object key) { - E element = lookup(id, false); - return element != null && !(element instanceof Descriptor); + return keySet().contains(key); } - public final boolean isRegistered(ID id) + public boolean containsValue(Object value) { - return lookup(id, false) != null; + return values().contains(value); } - public int size() + public boolean isEmpty() { - return getElementIDs().size(); + return keySet().isEmpty(); } - public final E lookup(ID id) + public V put(K key, V value) { - return lookup(id, isResolving()); + return getTransaction().put(key, value); } - public final Collection<E> getElements() + public void putAll(Map<? extends K, ? extends V> t) { - return getElements(isResolving()); + if (!t.isEmpty()) + { + Transaction transaction = getTransaction(); + Iterator<? extends Entry<? extends K, ? extends V>> i = t.entrySet().iterator(); + while (i.hasNext()) + { + Entry<? extends K, ? extends V> e = i.next(); + transaction.put(e.getKey(), e.getValue()); + } + } } - /** - * Synchronized to support {@link #resolveElement(IRegistryElement)} - */ - public final synchronized Collection<E> getElements(boolean resolve) + public V remove(Object key) { - Set<ID> elementKeys = getElementIDs(); - List<E> elements = new ArrayList(elementKeys.size()); - for (ID id : elementKeys) - { - elements.add(lookup(id, resolve)); - } + return getTransaction().remove(key); + } - return elements; + public int size() + { + return keySet().size(); } - public void addRegistryListener(IRegistryListener<ID, E> listener) + public void commit() { - listeners.add(listener); + synchronized (transactionLock) + { + if (transaction != null) + { + transaction.commit(); + } + } } - public void removeRegistryListener(IRegistryListener<ID, E> listener) + protected Transaction getTransaction() { - listeners.remove(listener); + synchronized (transactionLock) + { + if (transaction != null) + { + transaction = new Transaction(); + } + + transaction.increaseNesting(); + } + + return transaction; } public void dispose() @@ -117,13 +137,13 @@ public abstract class AbstractRegistry<ID, E extends IRegistryElement<ID>> imple listeners.clear(); } - protected void fireRegistryEvent(EventType eventType, E element) + protected void fireRegistryEvent(IRegistryEvent<K, V> event) { for (IRegistryListener listener : listeners) { try { - listener.notifyRegistryEvent(this, eventType, element); + listener.notifyRegistryEvent(event); } catch (Exception ex) { @@ -135,38 +155,73 @@ public abstract class AbstractRegistry<ID, E extends IRegistryElement<ID>> imple } } - protected void fireElementRegistered(E element) - { - fireRegistryEvent(EventType.REGISTERED, element); - } - - protected void fireElementDeregistering(E element) - { - fireRegistryEvent(EventType.DEREGISTERING, element); - } + protected abstract V register(K key, V value); - protected void fireElementResolved(E element) - { - fireRegistryEvent(EventType.RESOLVED, element); - } + protected abstract V deregister(Object key); /** - * Calling thread must already synchronize on this {@link IRegistry}! + * @author Eike Stepper */ - protected E resolveElement(E element) + protected class Transaction { - if (element instanceof Descriptor) + private int nesting; + + private List<IRegistryDelta<K, V>> deltas = new ArrayList(); + + public Transaction() { - element = (E)((Descriptor)element).resolve(); - replaceElement(element.getID(), element); - fireElementResolved(element); } - return element; - } + public void increaseNesting() + { + ++nesting; + } - /** - * Calling thread must already synchronize on this {@link IRegistry}! - */ - protected abstract void replaceElement(ID id, E element); + public V put(K key, V value) + { + V oldValue = register(key, value); + if (oldValue != null) + { + rememberDeregistering(key, oldValue); + } + + rememberRegistered(key, value); + return oldValue; + } + + public V remove(Object key) + { + V value = deregister(key); + if (value != null) + { + rememberDeregistering(key, value); + } + + return value; + } + + public void commit() + { + if (--nesting == 0) + { + if (!deltas.isEmpty()) + { + fireRegistryEvent(new RegistryEvent<K, V>(AbstractRegistry.this, deltas)); + } + + deltas = null; + transaction = null; + } + } + + protected void rememberRegistered(K key, V value) + { + deltas.add(new RegistryDelta(key, value, IRegistryDelta.REGISTERED)); + } + + protected void rememberDeregistering(Object key, V value) + { + deltas.add(new RegistryDelta(key, value, IRegistryDelta.DEREGISTERING)); + } + } } diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java index e73fa9ae02..23bd70bc6b 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/HashMapRegistry.java @@ -16,30 +16,33 @@ import java.util.Map; /** * @author Eike Stepper */ -public class HashMapRegistry<ID, E extends IRegistryElement<ID>> extends - AbstractMappingRegistry<ID, E> +public class HashMapRegistry<K, V> extends AbstractMappingRegistry<K, V> { - private Map<ID, E> map; + private Map<K, V> map; public HashMapRegistry() { - this(DEFAULT_RESOLVING); + map = new HashMap(); } - public HashMapRegistry(boolean resolving) + public HashMapRegistry(int initialCapacity) { - super(resolving); - this.map = createMap(); + map = new HashMap(initialCapacity); } - @Override - protected Map<ID, E> getMap() + public HashMapRegistry(int initialCapacity, float loadFactor) { - return map; + map = new HashMap(initialCapacity, loadFactor); } - protected Map<ID, E> createMap() + public HashMapRegistry(Map<? extends K, ? extends V> m) { - return new HashMap(0); + map = new HashMap(m); + } + + @Override + protected Map<K, V> getMap() + { + return map; } } diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java index 510c2f4eec..b0550c4f0a 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistry.java @@ -10,45 +10,18 @@ **************************************************************************/ package org.eclipse.net4j.util.registry; -import java.util.Collection; -import java.util.Set; +import java.util.Map; /** - * Implementation note: {@link Object#equals(Object)} and - * {@link Object#hashCode()} are based on pointer equality. - * <p> - * * @author Eike Stepper */ -public interface IRegistry<ID, E extends IRegistryElement<ID>> +public interface IRegistry<K, V> extends Map<K, V> { - public void setResolving(boolean resolving); - - public boolean isResolving(); - - public boolean isResolved(ID id); - - public boolean isRegistered(ID id); - - public int size(); - - public void register(E element); - - public void deregister(ID id); - - public E lookup(ID id); - - public E lookup(ID id, boolean resolve); - - public Set<ID> getElementIDs(); - - public Collection<E> getElements(); - - public Collection<E> getElements(boolean resolve); + public void addRegistryListener(IRegistryListener<K, V> listener); - public void addRegistryListener(IRegistryListener<ID, E> listener); + public void removeRegistryListener(IRegistryListener<K, V> listener); - public void removeRegistryListener(IRegistryListener<ID, E> listener); + public void commit(); public void dispose(); } diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryDelta.java index 33083a5c3c..d0750c8b4d 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryElement.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryDelta.java @@ -10,18 +10,16 @@ **************************************************************************/ package org.eclipse.net4j.util.registry; +import java.util.Map; + /** * @author Eike Stepper */ -public interface IRegistryElement<ID> +public interface IRegistryDelta<K, V> extends Map.Entry<K, V> { - public ID getID(); + public static final int REGISTERED = 1; + + public static final int DEREGISTERING = 2; - /** - * @author Eike Stepper - */ - public interface Descriptor<ID> extends IRegistryElement<ID> - { - public IRegistryElement<ID> resolve(); - } -}
\ No newline at end of file + public int getKind(); +} diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryEvent.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryEvent.java new file mode 100644 index 0000000000..56b13f82ec --- /dev/null +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryEvent.java @@ -0,0 +1,21 @@ +/*************************************************************************** + * Copyright (c) 2004, 2005, 2006 Eike Stepper, Germany. + * 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.net4j.util.registry; + +/** + * @author Eike Stepper + */ +public interface IRegistryEvent<ID, E> +{ + public IRegistry<ID, E> getRegistry(); + + public IRegistryDelta<ID, E>[] getDeltas(); +} diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryListener.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryListener.java index 49d18a62e1..91d71032fb 100644 --- a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryListener.java +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/IRegistryListener.java @@ -3,16 +3,7 @@ package org.eclipse.net4j.util.registry; /** * @author Eike Stepper */ -public interface IRegistryListener<ID, E extends IRegistryElement<ID>> +public interface IRegistryListener<ID, E> { - public void notifyRegistryEvent(IRegistry<ID, E> registry, IRegistryListener.EventType eventType, - E element); - - /** - * @author Eike Stepper - */ - public enum EventType - { - REGISTERED, DEREGISTERING, RESOLVED - } + public void notifyRegistryEvent(IRegistryEvent<ID, E> event); }
\ No newline at end of file diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryDelta.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryDelta.java new file mode 100644 index 0000000000..4506606571 --- /dev/null +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryDelta.java @@ -0,0 +1,40 @@ +package org.eclipse.net4j.util.registry; + +/** + * @author Eike Stepper + */ +public class RegistryDelta<K, V> implements IRegistryDelta<K, V> +{ + private K key; + + private V value; + + private int kind; + + public RegistryDelta(K key, V value, int kind) + { + this.key = key; + this.value = value; + this.kind = kind; + } + + public K getKey() + { + return key; + } + + public V getValue() + { + return value; + } + + public V setValue(V value) + { + throw new UnsupportedOperationException(); + } + + public int getKind() + { + return kind; + } +}
\ No newline at end of file diff --git a/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryEvent.java b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryEvent.java new file mode 100644 index 0000000000..8cf30b5cbc --- /dev/null +++ b/plugins/org.eclipse.net4j/src/org/eclipse/net4j/util/registry/RegistryEvent.java @@ -0,0 +1,29 @@ +package org.eclipse.net4j.util.registry; + +import java.util.List; + +/** + * @author Eike Stepper + */ +public class RegistryEvent<K, V> implements IRegistryEvent<K, V> +{ + private IRegistry<K, V> registry; + + private List<IRegistryDelta<K, V>> deltas; + + public RegistryEvent(IRegistry<K, V> registry, List<IRegistryDelta<K, V>> deltas) + { + this.registry = registry; + this.deltas = deltas; + } + + public IRegistry<K, V> getRegistry() + { + return registry; + } + + public IRegistryDelta<K, V>[] getDeltas() + { + return deltas.toArray(new IRegistryDelta[deltas.size()]); + } +}
\ No newline at end of file |