package com.netflix.evcache.pool;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.util.List;
import com.netflix.appinfo.InstanceInfo;
import com.netflix.config.ChainedDynamicProperty;
import com.netflix.discovery.DiscoveryClient;
import com.netflix.discovery.shared.Application;
import com.netflix.evcache.util.EVCacheConfig;
import net.spy.memcached.MemcachedNode;
import net.spy.memcached.util.DefaultKetamaNodeLocatorConfiguration;
public class EVCacheKetamaNodeLocatorConfiguration extends DefaultKetamaNodeLocatorConfiguration {
private final String appId;
private final ServerGroup serverGroup;
private final EVCacheClientPoolManager poolManager;
private final ChainedDynamicProperty.IntProperty bucketSize;
public EVCacheKetamaNodeLocatorConfiguration(String appId, ServerGroup serverGroup, EVCacheClientPoolManager poolManager) {
this.appId = appId;
this.serverGroup = serverGroup;
this.poolManager = poolManager;
bucketSize = EVCacheConfig.getInstance().getChainedIntProperty(appId + "." + serverGroup.getName() + ".bucket.size",appId + ".bucket.size", super.getNodeRepetitions());
}
/**
* Returns the number of discrete hashes that should be defined for each
* node in the continuum.
*
* @return NUM_REPS repetitions.
*/
public int getNodeRepetitions() {
return bucketSize.get().intValue();
}
/**
* Returns the socket address of a given MemcachedNode.
*
* @param node - The MemcachedNode which we're interested in
* @return The socket address of the given node format is of the following
* format "publicHostname/privateIp:port" (ex -
ec2-174-129-159-31.compute-1.amazonaws.com/10.125.47.114:11211)
*/
@Override
protected String getSocketAddressForNode(MemcachedNode node) {
String result = socketAddresses.get(node);
if(result == null) {
final SocketAddress socketAddress = node.getSocketAddress();
if(socketAddress instanceof InetSocketAddress) {
final InetSocketAddress isa = (InetSocketAddress)socketAddress;
if(poolManager.getDiscoveryClient() != null ) {
final DiscoveryClient mgr = poolManager.getDiscoveryClient();
final Application app = mgr.getApplication(appId);
if(app != null) {
final List<InstanceInfo> instances = app.getInstances();
for(InstanceInfo info : instances) {
final String hostName = info.getHostName();
if(hostName.equalsIgnoreCase(isa.getHostName())) {
final String ip = info.getIPAddr();
final String port = info.getMetadata().get("evcache.port");
result = hostName + '/' + ip + ':' + ((port != null) ? port : "11211");
break;
}
}
} else {
result = ((InetSocketAddress)socketAddress).getHostName() + '/' + ((InetSocketAddress)socketAddress).getAddress().getHostAddress() + ":11211";
}
} else {
result = ((InetSocketAddress)socketAddress).getHostName() + '/' + ((InetSocketAddress)socketAddress).getAddress().getHostAddress() + ":11211";
}
} else {
result=String.valueOf(socketAddress);
if (result.startsWith("/")) {
result = result.substring(1);
}
}
socketAddresses.put(node, result);
}
return result;
}
@Override
public String toString() {
return "EVCacheKetamaNodeLocatorConfiguration [app=" + appId + ", ServerGroup=" + serverGroup + ", BucketSize=" + getNodeRepetitions() + "]";
}
}