geronimo-scm mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From gdam...@apache.org
Subject svn commit: r553487 - in /geronimo/server/trunk/modules: geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/ geronimo-clustering-wadi/src/test/ geronimo-clustering-wadi/src/test/java/ geronimo-clustering-wadi/src/test/java/org/ ...
Date Thu, 05 Jul 2007 12:55:38 GMT
Author: gdamour
Date: Thu Jul  5 05:55:36 2007
New Revision: 553487

URL: http://svn.apache.org/viewvc?view=rev&rev=553487
Log:
Add Cluster and ClusterListener to the clustering API. Cluster represents a cluster, i.e.
a set of Nodes. Clients
can register a ClusterListener with a Cluster to be notified when Nodes are joining or leaving
the Cluster.

Provide a WADI implementation of these contracts.

Added:
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADICluster.java
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/
    geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/WADIClusterTest.java
    geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Cluster.java
    geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusterListener.java
Modified:
    geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADICluster.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADICluster.java?view=auto&rev=553487
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADICluster.java
(added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/main/java/org/apache/geronimo/clustering/wadi/WADICluster.java
Thu Jul  5 05:55:36 2007
@@ -0,0 +1,155 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.clustering.wadi;
+
+import java.util.Collection;
+import java.util.HashSet;
+import java.util.IdentityHashMap;
+import java.util.Set;
+
+import org.apache.geronimo.clustering.BasicNode;
+import org.apache.geronimo.clustering.Cluster;
+import org.apache.geronimo.clustering.ClusterListener;
+import org.apache.geronimo.clustering.Node;
+import org.apache.geronimo.gbean.GBeanInfo;
+import org.apache.geronimo.gbean.GBeanInfoBuilder;
+import org.apache.geronimo.gbean.GBeanLifecycle;
+import org.apache.geronimo.j2ee.j2eeobjectnames.NameFactory;
+import org.codehaus.wadi.group.LocalPeer;
+import org.codehaus.wadi.group.Peer;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public class WADICluster implements GBeanLifecycle, Cluster {
+    private final DispatcherHolder dispatcherHolder;
+    private org.codehaus.wadi.group.Cluster cluster;
+    private final IdentityHashMap<ClusterListener, org.codehaus.wadi.group.ClusterListener>
listenerToWADIListener;
+    
+    public WADICluster(DispatcherHolder dispatcherHolder) {
+        if (null == dispatcherHolder) {
+            throw new IllegalArgumentException("dispatcherHolder is required");
+        }
+        this.dispatcherHolder = dispatcherHolder;
+        
+        listenerToWADIListener = new IdentityHashMap<ClusterListener, org.codehaus.wadi.group.ClusterListener>();
+    }
+
+    public void doStart() throws Exception {
+        cluster = dispatcherHolder.getDispatcher().getCluster();
+    }
+    
+    public void doStop() throws Exception {
+        clearListeners();
+    }
+
+    public void doFail() {
+        clearListeners();
+    }
+
+    public String getName() {
+        return cluster.getClusterName();
+    }
+
+    public Node getLocalNode() {
+        LocalPeer localPeer = cluster.getLocalPeer();
+        return new BasicNode(localPeer.getName());
+    }
+    
+    public Set<Node> getRemoteNodes() {
+        Collection<Peer> peers = cluster.getRemotePeers().values();
+        Set<Node> nodes = wrapAsNode(peers);
+        return nodes;
+    }
+
+    public void addClusterListener(ClusterListener listener) {
+        if (null == listener) {
+            throw new IllegalArgumentException("listener is required");
+        }
+        GeronimoClusterListenerAdaptor wadiListener = new GeronimoClusterListenerAdaptor(listener);
+        listenerToWADIListener.put(listener, wadiListener);
+        cluster.addClusterListener(wadiListener);
+    }
+    
+    public void removeClusterListener(ClusterListener listener) {
+        org.codehaus.wadi.group.ClusterListener wadiListener = listenerToWADIListener.remove(listener);
+        if (null == wadiListener) {
+            throw new IllegalArgumentException(listener + " is not registered");
+        }
+        cluster.removeClusterListener(wadiListener);
+    }
+    
+    protected void clearListeners() {
+        for (org.codehaus.wadi.group.ClusterListener wadiListener : listenerToWADIListener.values())
{
+            cluster.removeClusterListener(wadiListener);
+        }
+        
+        listenerToWADIListener.clear();
+    }
+    
+    protected Set<Node> wrapAsNode(Collection<Peer> peers) {
+        Set<Node> nodes = new HashSet<Node>();
+        for (Peer peer : peers) {
+            nodes.add(new BasicNode(peer.getName()));
+        }
+        return nodes;
+    }
+
+    protected class GeronimoClusterListenerAdaptor implements org.codehaus.wadi.group.ClusterListener
{
+        private final ClusterListener listener;
+
+        public GeronimoClusterListenerAdaptor(ClusterListener listener) {
+            this.listener = listener;
+        }
+
+        public void onListenerRegistration(org.codehaus.wadi.group.Cluster cluster, Set existing)
{
+            Set<Node> existingNodes = wrapAsNode(existing);
+            listener.onListenerRegistration(WADICluster.this, existingNodes);
+        }
+        
+        public void onMembershipChanged(org.codehaus.wadi.group.Cluster cluster, Set joiners,
Set leavers) {
+            Set<Node> joinerNodes = wrapAsNode(joiners);
+            Set<Node> leaverNodes = wrapAsNode(leavers);
+            listener.onMembershipChanged(WADICluster.this, joinerNodes, leaverNodes);
+        }
+        
+    }
+    
+    public static final GBeanInfo GBEAN_INFO;
+
+    public static final String GBEAN_REF_DISPATCHER_HOLDER = "DispatcherHolder";
+
+    static {
+        GBeanInfoBuilder infoBuilder = GBeanInfoBuilder.createStatic("WADI Cluster",
+            WADICluster.class,
+            NameFactory.GERONIMO_SERVICE);
+
+        infoBuilder.addReference(GBEAN_REF_DISPATCHER_HOLDER, DispatcherHolder.class, NameFactory.GERONIMO_SERVICE);
+
+        infoBuilder.addInterface(Cluster.class);
+
+        infoBuilder.setConstructor(new String[] {GBEAN_REF_DISPATCHER_HOLDER});
+
+        GBEAN_INFO = infoBuilder.getBeanInfo();
+    }
+
+    public static GBeanInfo getGBeanInfo() {
+        return GBEAN_INFO;
+    }
+    
+}

Added: geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/WADIClusterTest.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/WADIClusterTest.java?view=auto&rev=553487
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/WADIClusterTest.java
(added)
+++ geronimo/server/trunk/modules/geronimo-clustering-wadi/src/test/java/org/apache/geronimo/clustering/wadi/WADIClusterTest.java
Thu Jul  5 05:55:36 2007
@@ -0,0 +1,245 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.clustering.wadi;
+
+import java.io.IOException;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+
+import org.apache.geronimo.clustering.BasicNode;
+import org.apache.geronimo.clustering.ClusterListener;
+import org.apache.geronimo.clustering.Node;
+import org.codehaus.wadi.group.Address;
+import org.codehaus.wadi.group.LocalPeer;
+import org.codehaus.wadi.group.Peer;
+
+import com.agical.rmock.core.Action;
+import com.agical.rmock.core.MethodHandle;
+import com.agical.rmock.core.describe.ExpressionDescriber;
+import com.agical.rmock.core.match.operator.AbstractExpression;
+import com.agical.rmock.extension.junit.RMockTestCase;
+
+/**
+ * 
+ * @version $Rev$ $Date$
+ */
+public class WADIClusterTest extends RMockTestCase {
+
+    private org.codehaus.wadi.group.Cluster wadiCluster;
+    private LocalPeer localPeer;
+    private Peer peer1;
+    private Peer peer2;
+    private WADICluster cluster;
+    private ClusterListener listener;
+    
+    @Override
+    protected void setUp() throws Exception {
+        DispatcherHolder dispatcherHolder = (DispatcherHolder) mock(DispatcherHolder.class);
+
+        wadiCluster = dispatcherHolder.getDispatcher().getCluster();
+        wadiCluster.getClusterName();
+        modify().multiplicity(expect.from(0)).returnValue("name");
+
+        localPeer = wadiCluster.getLocalPeer();
+        modify().multiplicity(expect.from(0));
+        localPeer.getName();
+        modify().multiplicity(expect.from(0)).returnValue("localPeerName");
+        
+        Map<Address, Peer> remotePeers = new HashMap<Address, Peer>();
+        peer1 = addPeer("peer1", remotePeers);
+        peer2 = addPeer("peer2", remotePeers);
+        
+        wadiCluster.getRemotePeers();
+        modify().multiplicity(expect.from(0)).returnValue(remotePeers);
+        
+        cluster = new WADICluster(dispatcherHolder);
+        listener = (ClusterListener) mock(ClusterListener.class);
+    }
+
+    private Peer addPeer(String peerName, Map<Address, Peer> remotePeers) {
+        Peer peer = (Peer) mock(Peer.class, peerName);
+
+        Address address = peer.getAddress();
+        modify().multiplicity(expect.from(0));
+        peer.getName();
+        modify().multiplicity(expect.from(0)).returnValue(peerName);
+        
+        remotePeers.put(address, peer);
+        
+        return peer;
+    }
+    
+    public void testGetName() throws Exception {
+        startVerification();
+        cluster.doStart();
+        
+        assertEquals(wadiCluster.getClusterName(), cluster.getName());
+    }
+    
+    public void testGetLocalNode() throws Exception {
+        startVerification();
+        cluster.doStart();
+        
+        assertEquals(localPeer.getName(), cluster.getLocalNode().getName());
+    }
+    
+    public void testGetRemotePeers() throws Exception {
+        startVerification();
+        cluster.doStart();
+
+        Set<Node> remoteNodes = cluster.getRemoteNodes();
+        assertEquals(2, remoteNodes.size());
+        assertTrue(remoteNodes.contains(new BasicNode(peer1.getName())));
+        assertTrue(remoteNodes.contains(new BasicNode(peer2.getName())));
+    }
+    
+    public void testAddClusterListener() throws Exception {
+        wadiCluster.addClusterListener(null);
+        modify().args(new AbstractExpression() {
+
+            public void describeWith(ExpressionDescriber arg0) throws IOException {
+            }
+
+            public boolean passes(Object arg0) {
+                assertTrue(arg0 instanceof org.codehaus.wadi.group.ClusterListener);
+                return true;
+            }
+            
+        });
+        
+        startVerification();
+        cluster.doStart();
+        
+        cluster.addClusterListener(listener);
+    }
+    
+    public void testAddNullClusterListenerThrowsException() throws Exception {
+        startVerification();
+        cluster.doStart();
+        
+        try {
+            cluster.addClusterListener(null);
+            fail();
+        } catch (IllegalArgumentException e) {
+        }
+    }
+    
+    public void testRemoveClusterListener() throws Exception {
+        AbstractExpression assertSame = new AssertSameWADIListener();
+        wadiCluster.addClusterListener(null);
+        modify().args(assertSame);
+        wadiCluster.removeClusterListener(null);
+        modify().args(assertSame);
+        
+        startVerification();
+        cluster.doStart();
+
+        cluster.addClusterListener(listener);
+        cluster.removeClusterListener(listener);
+    }
+    
+    public void testRemoveUndefinedClusterListenerThrowsException() throws Exception {
+        startVerification();
+        cluster.doStart();
+
+        try {
+            cluster.removeClusterListener(listener);
+            fail();
+        } catch (IllegalArgumentException e) {
+        }
+    }
+    
+    public void testClusterListenerRegistrationCallback() throws Exception {
+        Set<Node> existing = new HashSet<Node>();
+        existing.add(new BasicNode("peer1"));
+        listener.onListenerRegistration(cluster, existing);
+        
+        wadiCluster.addClusterListener(null);
+        modify().args(is.ANYTHING).perform(new Action() {
+
+            public Object invocation(Object[] arg0, MethodHandle arg1) throws Throwable {
+                org.codehaus.wadi.group.ClusterListener wadiListener = (org.codehaus.wadi.group.ClusterListener)
arg0[0];
+                wadiListener.onListenerRegistration(wadiCluster, Collections.singleton(peer1));;
+                return null;
+            }
+            
+        });
+
+        startVerification();
+        cluster.doStart();
+        
+        cluster.addClusterListener(listener);
+    }
+    
+    public void testClusterListenerMembershipChangeCallback() throws Exception {
+        Set<Node> joiners = new HashSet<Node>();
+        joiners.add(new BasicNode("peer1"));
+        Set<Node> leavers = new HashSet<Node>();
+        leavers.add(new BasicNode("peer2"));
+        listener.onMembershipChanged(cluster, joiners, leavers);
+        
+        wadiCluster.addClusterListener(null);
+        modify().args(is.ANYTHING).perform(new Action() {
+
+            public Object invocation(Object[] arg0, MethodHandle arg1) throws Throwable {
+                org.codehaus.wadi.group.ClusterListener wadiListener = (org.codehaus.wadi.group.ClusterListener)
arg0[0];
+                wadiListener.onMembershipChanged(wadiCluster, Collections.singleton(peer1),
Collections.singleton(peer2));
+                return null;
+            }
+            
+        });
+
+        startVerification();
+        cluster.doStart();
+        
+        cluster.addClusterListener(listener);
+    }
+    
+    public void testRemoveListenersOnStopOrFail() throws Exception {
+        AbstractExpression assertSame = new AssertSameWADIListener();
+        wadiCluster.addClusterListener(null);
+        modify().args(assertSame);
+        wadiCluster.removeClusterListener(null);
+        modify().args(assertSame);
+        
+        startVerification();
+        cluster.doStart();
+        
+        cluster.addClusterListener(listener);
+        cluster.doStop();
+    }
+    
+    private final class AssertSameWADIListener extends AbstractExpression {
+        private org.codehaus.wadi.group.ClusterListener wadiListener;
+
+        public void describeWith(ExpressionDescriber arg0) throws IOException {
+        }
+
+        public boolean passes(Object arg0) {
+            if (null == wadiListener) {
+                wadiListener = (org.codehaus.wadi.group.ClusterListener) arg0;
+            } else {
+                assertSame(wadiListener, arg0);
+            }
+            return true;
+        }
+    }
+
+}

Modified: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java?view=diff&rev=553487&r1=553486&r2=553487
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java
(original)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/BasicNode.java
Thu Jul  5 05:55:36 2007
@@ -28,11 +28,28 @@
     private final String name;
     
     public BasicNode(String name) {
+        if (null == name) {
+            throw new IllegalArgumentException("name is required");
+        }
         this.name = name;
     }
 
     public String getName() {
         return name;
+    }
+    
+    @Override
+    public boolean equals(Object obj) {
+        if (!(obj instanceof BasicNode)) {
+            return false;
+        }
+        BasicNode other = (BasicNode) obj;
+        return name.equals(other.name);
+    }
+    
+    @Override
+    public int hashCode() {
+        return name.hashCode();
     }
     
     public static final GBeanInfo GBEAN_INFO;

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Cluster.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Cluster.java?view=auto&rev=553487
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Cluster.java
(added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/Cluster.java
Thu Jul  5 05:55:36 2007
@@ -0,0 +1,36 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.clustering;
+
+import java.util.Set;
+
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public interface Cluster {
+    String getName();
+
+    Node getLocalNode();
+    
+    Set<Node> getRemoteNodes();
+    
+    void addClusterListener(ClusterListener listener);
+
+    void removeClusterListener(ClusterListener listener);
+}

Added: geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusterListener.java
URL: http://svn.apache.org/viewvc/geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusterListener.java?view=auto&rev=553487
==============================================================================
--- geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusterListener.java
(added)
+++ geronimo/server/trunk/modules/geronimo-clustering/src/main/java/org/apache/geronimo/clustering/ClusterListener.java
Thu Jul  5 05:55:36 2007
@@ -0,0 +1,30 @@
+/**
+ *  Licensed to the Apache Software Foundation (ASF) under one or more
+ *  contributor license agreements.  See the NOTICE file distributed with
+ *  this work for additional information regarding copyright ownership.
+ *  The ASF licenses this file to You under the Apache License, Version 2.0
+ *  (the "License"); you may not use this file except in compliance with
+ *  the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ *  Unless required by applicable law or agreed to in writing, software
+ *  distributed under the License is distributed on an "AS IS" BASIS,
+ *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ *  See the License for the specific language governing permissions and
+ *  limitations under the License.
+ */
+package org.apache.geronimo.clustering;
+
+import java.util.Set;
+
+
+/**
+ *
+ * @version $Rev$ $Date$
+ */
+public interface ClusterListener {
+    void onListenerRegistration(Cluster cluster, Set<Node> existing);
+    
+    void onMembershipChanged(Cluster cluster, Set<Node> joiners, Set<Node> leavers);
+}



Mime
View raw message