package com.facebook.infrastructure.locator; import java.math.BigInteger; import java.util.ArrayList; import java.util.Collections; import java.util.List; import java.util.Map; import com.facebook.infrastructure.config.DatabaseDescriptor; import com.facebook.infrastructure.net.EndPoint; /** * This class returns the nodes responsible for a given * key but does not respect rack awareness. Basically * returns the 3 nodes that lie right next to each other * on the ring. */ public class RackUnawareStrategy extends AbstractStrategy { public RackUnawareStrategy(TokenMetadata tokenMetadata) { super(tokenMetadata); } public EndPoint[] getStorageEndPoints(BigInteger token) { return getStorageEndPoints(token, tokenMetadata_.cloneTokenEndPointMap()); } public EndPoint[] getStorageEndPoints(BigInteger token, Map<BigInteger, EndPoint> tokenToEndPointMap) { List<BigInteger> tokens = new ArrayList<BigInteger>(tokenToEndPointMap.keySet()); Collections.sort(tokens); // TODO can we do this only once per token update? int index = Collections.binarySearch(tokens, token); // find "primary" endpoint final int tokensSize = tokens.size(); if(index < 0) { index = (index + 1) * (-1); if (index >= tokensSize) index = 0; } // how many tokens should we return? int N = DatabaseDescriptor.getReplicationFactor(); if (N > tokensSize) { logger_.warn("Replication factor is " + N + " but only " + tokensSize + " nodes available"); N = tokensSize; } // loop through the list, starting with the "primary" endpoint that binarysearch found, and add until we have N nodes. List<EndPoint> endPoints = new ArrayList<EndPoint>(); for (int i = index; endPoints.size() < N; i = (i + 1) % tokensSize) { endPoints.add(tokenToEndPointMap.get(tokens.get(i))); } retrofitPorts(endPoints); return endPoints.toArray(new EndPoint[endPoints.size()]); } }