Author: jbellis
Date: Tue Oct 20 17:48:52 2009
New Revision: 827744

URL: http://svn.apache.org/viewvc?rev=827744&view=rev
Log:
fix HH to not give up when any node is live
patch by jbellis; reviewed by eevans for CASSANDRA-496

Modified:
    
incubator/cassandra/trunk/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java

Modified: 
incubator/cassandra/trunk/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java
URL: 
http://svn.apache.org/viewvc/incubator/cassandra/trunk/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java?rev=827744&r1=827743&r2=827744&view=diff
==============================================================================
--- 
incubator/cassandra/trunk/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java
 (original)
+++ 
incubator/cassandra/trunk/src/java/org/apache/cassandra/locator/AbstractReplicationStrategy.java
 Tue Oct 20 17:48:52 2009
@@ -18,12 +18,7 @@
 */
 package org.apache.cassandra.locator;
 
-import java.util.ArrayList;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
+import java.util.*;
 
 import org.apache.log4j.Logger;
 
@@ -31,6 +26,7 @@
 import org.apache.cassandra.dht.IPartitioner;
 import org.apache.cassandra.gms.FailureDetector;
 import org.apache.cassandra.net.EndPoint;
+import org.apache.cassandra.service.StorageService;
 
 /**
  * This class contains a helper method that will be used by
@@ -83,51 +79,48 @@
 
     private Map<EndPoint, EndPoint> getHintedMapForEndpoints(EndPoint[] topN)
     {
-        List<EndPoint> liveList = new ArrayList<EndPoint>();
+        Set<EndPoint> usedEndpoints = new HashSet<EndPoint>();
         Map<EndPoint, EndPoint> map = new HashMap<EndPoint, EndPoint>();
 
-        for( int i = 0 ; i < topN.length ; i++)
+        for (EndPoint ep : topN)
         {
-            if( FailureDetector.instance().isAlive(topN[i]))
+            if (FailureDetector.instance().isAlive(ep))
             {
-                map.put(topN[i], topN[i]);
-                liveList.add(topN[i]) ;
+                map.put(ep, ep);
+                usedEndpoints.add(ep);
             }
             else
             {
-                EndPoint endPoint = null;
+                // find another endpoint to store a hint on.  prefer endpoints 
that aren't already in use
+                EndPoint hintLocation = null;
                 Map<Token, EndPoint> tokenToEndPointMap = 
tokenMetadata_.cloneTokenEndPointMap();
                 List tokens = new ArrayList(tokenToEndPointMap.keySet());
                 Collections.sort(tokens);
-                Token token = tokenMetadata_.getToken(topN[i]);
+                Token token = tokenMetadata_.getToken(ep);
                 int index = Collections.binarySearch(tokens, token);
-                if(index < 0)
+                if (index < 0)
                 {
                     index = (index + 1) * (-1);
-                    if (index >= tokens.size())
+                    if (index >= tokens.size()) // handle wrap
                         index = 0;
                 }
                 int totalNodes = tokens.size();
-                int startIndex = (index+1)%totalNodes;
-                for (int i1 = startIndex, count = 1; count < totalNodes ; 
++count, i1 = (i1 +1)%totalNodes)
+                int startIndex = (index + 1) % totalNodes;
+                for (int i = startIndex, count = 1; count < totalNodes; 
++count, i = (i + 1) % totalNodes)
                 {
-                    EndPoint tmpEndPoint = 
tokenToEndPointMap.get(tokens.get(i1));
-                    if(FailureDetector.instance().isAlive(tmpEndPoint) && 
!Arrays.asList(topN).contains(tmpEndPoint) && !liveList.contains(tmpEndPoint))
+                    EndPoint tmpEndPoint = 
tokenToEndPointMap.get(tokens.get(i));
+                    if (FailureDetector.instance().isAlive(tmpEndPoint) && 
!Arrays.asList(topN).contains(tmpEndPoint) && 
!usedEndpoints.contains(tmpEndPoint))
                     {
-                        endPoint = tmpEndPoint;
+                        hintLocation = tmpEndPoint;
                         break;
                     }
                 }
-                if(endPoint != null)
-                {
-                    map.put(endPoint, topN[i]);
-                    liveList.add(endPoint) ;
-                }
-                else
-                {
-                    // log a warning , maybe throw an exception
-                    logger_.warn("Unable to find a live Endpoint we might be 
out of live nodes , This is dangerous !!!!");
-                }
+                // if all endpoints are already in use, might as well store it 
locally to save the network trip
+                if (hintLocation == null)
+                    hintLocation = StorageService.getLocalControlEndPoint();
+
+                map.put(hintLocation, ep);
+                usedEndpoints.add(hintLocation);
             }
         }
         return map;


Reply via email to