Clover coverage report - ActiveCluster - 1.1-SNAPSHOT
Coverage timestamp: Tue May 24 2005 08:48:28 BST
file stats: LOC: 266   Methods: 20
NCLOC: 189   Classes: 2
30 day Evaluation Version distributed via the Maven Jar Repository. Clover is not free. You have 30 days to evaluate it. Please visit http://www.thecortex.net/clover to obtain a licensed version of Clover
 
 Source file Conditionals Statements Methods TOTAL
StateServiceImpl.java 0% 0% 0% 0%
coverage
 1   
 /** 
 2   
  * 
 3   
  * Copyright 2004 Protique Ltd
 4   
  * 
 5   
  * Licensed under the Apache License, Version 2.0 (the "License"); 
 6   
  * you may not use this file except in compliance with the License. 
 7   
  * You may obtain a copy of the License at 
 8   
  * 
 9   
  * http://www.apache.org/licenses/LICENSE-2.0
 10   
  * 
 11   
  * Unless required by applicable law or agreed to in writing, software
 12   
  * distributed under the License is distributed on an "AS IS" BASIS, 
 13   
  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
 14   
  * See the License for the specific language governing permissions and 
 15   
  * limitations under the License. 
 16   
  * 
 17   
  **/
 18   
 package org.activecluster.impl;
 19   
 
 20   
 import org.apache.commons.logging.Log;
 21   
 import org.apache.commons.logging.LogFactory;
 22   
 import org.activecluster.Cluster;
 23   
 import org.activecluster.ClusterEvent;
 24   
 import org.activecluster.ClusterListener;
 25   
 import org.activecluster.Node;
 26   
 import org.activecluster.election.ElectionStrategy;
 27   
 import org.activecluster.election.impl.BullyElectionStrategy;
 28   
 
 29   
 import javax.jms.Destination;
 30   
 import javax.jms.JMSException;
 31   
 import java.util.ArrayList;
 32   
 import java.util.Collections;
 33   
 import java.util.HashMap;
 34   
 import java.util.Iterator;
 35   
 import java.util.List;
 36   
 import java.util.Map;
 37   
 import java.util.Map.Entry;
 38   
 import java.util.Timer;
 39   
 import java.util.TimerTask;
 40   
 
 41   
 
 42   
 /**
 43   
  * Represents a node list
 44   
  *
 45   
  * @version $Revision: 1.1 $
 46   
  */
 47   
 public class StateServiceImpl implements StateService {
 48   
 
 49   
     private final static Log log = LogFactory.getLog(StateServiceImpl.class);
 50   
     private Cluster cluster;
 51   
     private Object clusterLock;
 52   
     private Map nodes = new HashMap();
 53   
     private long inactiveTime;
 54   
     private List listeners = Collections.synchronizedList(new ArrayList());
 55   
     private Destination localDestination;
 56   
     private Runnable localNodePing;
 57   
     private Timer timer;
 58   
     private NodeImpl coordinator;
 59   
     private ElectionStrategy electionStrategy;
 60   
 
 61  0
     public StateServiceImpl(Cluster cluster, Object clusterLock, Runnable localNodePing, Timer timer, long inactiveTime) {
 62  0
         this.cluster = cluster;
 63  0
         this.clusterLock = clusterLock;
 64  0
         this.localDestination = cluster.getLocalNode().getDestination();
 65  0
         this.localNodePing = localNodePing;
 66  0
         this.timer = timer;
 67  0
         this.inactiveTime = inactiveTime;
 68  0
         long delay = inactiveTime / 3;
 69  0
         timer.scheduleAtFixedRate(createTimerTask(), delay, delay);
 70  0
         (this.coordinator = (NodeImpl) cluster.getLocalNode()).setCoordinator(true);
 71  0
         this.electionStrategy = new BullyElectionStrategy();
 72   
     }
 73   
 
 74   
     /**
 75   
      * @return the current election strategy
 76   
      */
 77  0
     public ElectionStrategy getElectionStrategy() {
 78  0
         return electionStrategy;
 79   
     }
 80   
 
 81   
     /**
 82   
      * set the election strategy
 83   
      *
 84   
      * @param electionStrategy
 85   
      */
 86  0
     public void setElectionStrategy(ElectionStrategy electionStrategy) {
 87  0
         this.electionStrategy = electionStrategy;
 88   
     }
 89   
 
 90  0
     public long getInactiveTime() {
 91  0
         return inactiveTime;
 92   
     }
 93   
 
 94  0
     public void setInactiveTime(long inactiveTime) {
 95  0
         this.inactiveTime = inactiveTime;
 96   
     }
 97   
 
 98  0
     public synchronized Map getNodes() {
 99  0
         HashMap answer = new HashMap(nodes.size());
 100  0
         for (Iterator iter = nodes.entrySet().iterator(); iter.hasNext();) {
 101  0
             Map.Entry entry = (Map.Entry) iter.next();
 102  0
             Destination key = (Destination) entry.getKey();
 103  0
             NodeEntry nodeEntry = (NodeEntry) entry.getValue();
 104  0
             answer.put(key, nodeEntry.node);
 105   
         }
 106  0
         return answer;
 107   
     }
 108   
 
 109  0
     public synchronized void keepAlive(Node node) {
 110  0
         Destination key = node.getDestination();
 111  0
         if (!localDestination.equals(key)) {
 112  0
             NodeEntry entry = (NodeEntry) nodes.get(key);
 113  0
             if (entry == null) {
 114  0
                 entry = new NodeEntry();
 115  0
                 entry.node = node;
 116  0
                 nodes.put(key, entry);
 117  0
                 nodeAdded(node);
 118  0
                 synchronized (clusterLock) {
 119  0
                     clusterLock.notifyAll();
 120   
                 }
 121   
             }
 122   
             else {
 123   
                 // has the data changed
 124  0
                 if (stateHasChanged(entry.node, node)) {
 125  0
                     entry.node = node;
 126  0
                     nodeUpdated(node);
 127   
                 }
 128   
             }
 129   
 
 130   
             // lets update the timer at which the node will be considered
 131   
             // to be dead
 132  0
             entry.lastKeepAlive = getTimeMillis();
 133   
         }
 134   
     }
 135   
 
 136  0
     public synchronized void shutdown(Node node) {
 137  0
         Destination key = node.getDestination();
 138  0
         nodes.remove(key);
 139   
 
 140  0
         ClusterEvent event = new ClusterEvent(cluster, node, ClusterEvent.ADD_NODE);
 141   
         // lets take a copy to make contention easier
 142  0
         Object[] array = listeners.toArray();
 143  0
         for (int i = 0, size = array.length; i < size; i++) {
 144  0
             ClusterListener listener = (ClusterListener) array[i];
 145  0
             listener.onNodeRemoved(event);
 146   
         }
 147   
     }
 148   
 
 149  0
     public synchronized void checkForTimeouts() {
 150  0
         localNodePing.run();
 151  0
         long time = getTimeMillis();
 152  0
         for (Iterator iter = nodes.entrySet().iterator(); iter.hasNext();) {
 153  0
             Map.Entry entry = (Entry) iter.next();
 154  0
             NodeEntry nodeEntry = (NodeEntry) entry.getValue();
 155  0
             if (nodeEntry.lastKeepAlive + inactiveTime < time) {
 156  0
                 iter.remove();
 157  0
                 nodeFailed(nodeEntry.node);
 158   
             }
 159   
         }
 160   
     }
 161   
 
 162  0
     public TimerTask createTimerTask() {
 163  0
         return new TimerTask() {
 164  0
             public void run() {
 165  0
                 checkForTimeouts();
 166   
             }
 167   
         };
 168   
     }
 169   
 
 170  0
     public void addClusterListener(ClusterListener listener) {
 171  0
         listeners.add(listener);
 172   
     }
 173   
 
 174  0
     public void removeClusterListener(ClusterListener listener) {
 175  0
         listeners.remove(listener);
 176   
     }
 177   
 
 178  0
     protected void nodeAdded(Node node) {
 179  0
         ClusterEvent event = new ClusterEvent(cluster, node, ClusterEvent.ADD_NODE);
 180   
         // lets take a copy to make contention easier
 181  0
         Object[] array = listeners.toArray();
 182  0
         for (int i = 0, size = array.length; i < size; i++) {
 183  0
             ClusterListener listener = (ClusterListener) array[i];
 184  0
             listener.onNodeAdd(event);
 185   
         }
 186  0
         doElection();
 187   
     }
 188   
 
 189  0
     protected void nodeUpdated(Node node) {
 190  0
         ClusterEvent event = new ClusterEvent(cluster, node, ClusterEvent.UPDATE_NODE);
 191   
         // lets take a copy to make contention easier
 192  0
         Object[] array = listeners.toArray();
 193  0
         for (int i = 0, size = array.length; i < size; i++) {
 194  0
             ClusterListener listener = (ClusterListener) array[i];
 195  0
             listener.onNodeUpdate(event);
 196   
         }
 197   
     }
 198   
 
 199  0
     protected void nodeFailed(Node node) {
 200  0
         ClusterEvent event = new ClusterEvent(cluster, node, ClusterEvent.REMOVE_NODE);
 201   
         // lets take a copy to make contention easier
 202  0
         Object[] array = listeners.toArray();
 203  0
         for (int i = 0, size = array.length; i < size; i++) {
 204  0
             ClusterListener listener = (ClusterListener) array[i];
 205  0
             listener.onNodeFailed(event);
 206   
         }
 207  0
         doElection();
 208   
     }
 209   
 
 210  0
     protected void coordinatorChanged(Node node) {
 211  0
         ClusterEvent event = new ClusterEvent(cluster, node, ClusterEvent.ELECTED_COORDINATOR);
 212   
         // lets take a copy to make contention easier
 213  0
         Object[] array = listeners.toArray();
 214  0
         for (int i = 0, size = array.length; i < size; i++) {
 215  0
             ClusterListener listener = (ClusterListener) array[i];
 216  0
             listener.onCoordinatorChanged(event);
 217   
         }
 218   
     }
 219   
 
 220  0
     protected void doElection() {
 221  0
         if (electionStrategy != null) {
 222  0
             try {
 223  0
                 NodeImpl newElected = (NodeImpl) electionStrategy.doElection(cluster);
 224  0
                 if (newElected != null && !newElected.equals(coordinator)) {
 225  0
                     coordinator.setCoordinator(false);
 226  0
                     coordinator = newElected;
 227  0
                     coordinator.setCoordinator(true);
 228  0
                     coordinatorChanged(coordinator);
 229   
                 }
 230   
             }
 231   
             catch (JMSException jmsEx) {
 232  0
                 log.error("do election failed", jmsEx);
 233   
             }
 234   
         }
 235   
     }
 236   
 
 237   
     /**
 238   
      * For performance we may wish to use a less granualar timing mechanism
 239   
      * only updating the time every x millis since we're only using
 240   
      * the time as a judge of when a node has not pinged for at least a few
 241   
      * hundred millis etc.
 242   
      */
 243  0
     protected long getTimeMillis() {
 244  0
         return System.currentTimeMillis();
 245   
     }
 246   
 
 247   
     protected static class NodeEntry {
 248   
         public Node node;
 249   
         public long lastKeepAlive;
 250   
     }
 251   
 
 252   
 
 253   
     /**
 254   
      * @return true if the node has changed state from the old in memory copy to the
 255   
      *         newly arrived copy
 256   
      */
 257  0
     protected boolean stateHasChanged(Node oldNode, Node newNode) {
 258  0
         Map oldState = oldNode.getState();
 259  0
         Map newState = newNode.getState();
 260  0
         if (oldState == newState) {
 261  0
             return false;
 262   
         }
 263  0
         return oldState == null || newState == null || !oldState.equals(newState);
 264   
     }
 265   
 }
 266