Skip to content

Commit

Permalink
end-to-end hashtag support and fixes
Browse files Browse the repository at this point in the history
  • Loading branch information
ipapapa committed Sep 29, 2017
1 parent a823877 commit 026c61a
Show file tree
Hide file tree
Showing 8 changed files with 830 additions and 677 deletions.
17 changes: 15 additions & 2 deletions dyno-core/src/main/java/com/netflix/dyno/connectionpool/Host.java
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@

import java.net.InetSocketAddress;

import com.netflix.dyno.connectionpool.Host.Status;
import com.netflix.dyno.connectionpool.impl.utils.ConfigUtils;

/**
Expand Down Expand Up @@ -45,7 +44,7 @@ public class Host implements Comparable<Host> {
private final InetSocketAddress socketAddress;
private final String rack;
private final String datacenter;
private final String hashtag;
private String hashtag;
private Status status = Status.Down;

public enum Status {
Expand Down Expand Up @@ -131,6 +130,10 @@ public String getRack() {
public String getHashtag() {
return hashtag;
}

public void setHashtag(String hashtag) {
this.hashtag = hashtag;
}

public Host setStatus(Status condition) {
status = condition;
Expand Down Expand Up @@ -171,6 +174,12 @@ public boolean equals(Object obj) {
return false;

Host other = (Host) obj;
/* we need a way to pass the information about the hashtag from the token map supplier
* to the host object.
*/
if (other.hashtag != null) {
setHashtag(other.hashtag);
}
boolean equals = true;

equals &= (hostname != null) ? hostname.equals(other.hostname) : other.hostname == null;
Expand All @@ -190,6 +199,10 @@ public int compareTo(Host o) {

@Override
public String toString() {
if (this.hashtag != null){
return "Host with Hashtag [hostname=" + hostname + ", ipAddress=" + ipAddress + ", port=" + port + ", rack: " + rack
+ ", datacenter: " + datacenter + ", status: " + status.name() + ", hashtag=" + hashtag + "]";
}
return "Host [hostname=" + hostname + ", ipAddress=" + ipAddress + ", port=" + port + ", rack: " + rack
+ ", datacenter: " + datacenter + ", status: " + status.name() + "]";
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -323,6 +323,10 @@ public boolean apply(HostToken x) {
return dcPools;
}

/**
* hPools comes from discovery.
* @param hPools
*/
public void initWithHosts(Map<Host, HostConnectionPool<CL>> hPools) {

// Get the list of tokens for these hosts
Expand All @@ -331,42 +335,41 @@ public void initWithHosts(Map<Host, HostConnectionPool<CL>> hPools) {

Map<HostToken, HostConnectionPool<CL>> tokenPoolMap = new HashMap<HostToken, HostConnectionPool<CL>>();

// Update inner state with the host tokens.

/* Initialize the hashtag with the first host (if hashtag is defined) */
this.hashtag = allHostTokens.get(0).getHost().getHashtag();

// Update inner state with the host tokens.
for (HostToken hToken : allHostTokens) {

/**
* Checking for defined hashtags if all of them are the same.
* If not we need to throw an exception.
*/
String hashtagNew = hToken.getHost().getHashtag();
if (this.hashtag!=null && !this.hashtag.equals(hashtagNew)){
logger.error("Hashtag mismatch across hashtags");
throw new RuntimeException("Hashtags are different across hosts");
}
this.hashtag = hashtagNew;

hostTokens.put(hToken.getHost(), hToken);
tokenPoolMap.put(hToken, hPools.get(hToken.getHost()));
}

Set<String> remoteDCs = new HashSet<String>();

/* Initialize the hashtag with the first host (if hashtag is defined) */
this.hashtag = hPools.keySet().iterator().next().getHashtag();

Set<String> remoteDCs = new HashSet<String>();
for (Host host : hPools.keySet()) {
String dc = host.getRack();
if (localRack != null && !localRack.isEmpty() && dc != null && !dc.isEmpty() && !localRack.equals(dc)) {
remoteDCs.add(dc);
}
/**
* Checking for defined hashtags if all of them are the same.
* If not we need to throw an exception.
*/
if(this.hashtag != null) {
String hashtagNew = host.getHashtag();
if (!this.hashtag.equals(hashtagNew)){
throw new RuntimeException("Hashtags are different across hosts");
}
this.hashtag = hashtagNew;
}
}
}

Map<HostToken, HostConnectionPool<CL>> localPools = getHostPoolsForDC(tokenPoolMap, localRack);
localSelector.initWithHosts(localPools);

if (localSelector.isTokenAware() && localRack != null) {
replicationFactor.set(calculateReplicationFactor(allHostTokens));
}
if (localSelector.isTokenAware() && localRack != null) {
replicationFactor.set(calculateReplicationFactor(allHostTokens));
}

for (String dc : remoteDCs) {
Map<HostToken, HostConnectionPool<CL>> dcPools = getHostPoolsForDC(tokenPoolMap, dc);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,9 @@
import java.util.concurrent.ConcurrentHashMap;

import org.apache.commons.lang3.StringUtils;
import org.slf4j.LoggerFactory;
import org.slf4j.Logger;


import com.netflix.dyno.connectionpool.BaseOperation;
import com.netflix.dyno.connectionpool.HostConnectionPool;
Expand All @@ -44,7 +47,7 @@
* @param <CL>
*/
public class TokenAwareSelection<CL> implements HostSelectionStrategy<CL> {

private final BinarySearchTokenMapper tokenMapper;

private final ConcurrentHashMap<Long, HostConnectionPool<CL>> tokenPools = new ConcurrentHashMap<Long, HostConnectionPool<CL>>();
Expand Down Expand Up @@ -78,9 +81,9 @@ public HostConnectionPool<CL> getPoolForOperation(BaseOperation<CL, ?> op, Strin
String key = op.getKey();

HostToken hToken = null;
if (hashtag == null || hashtag.isEmpty()) {
if (hashtag == null || hashtag.isEmpty()) {
hToken = this.getTokenForKey(key);
} else {
} else {
String hashValue = StringUtils.substringBetween(key,Character.toString(hashtag.charAt(0)), Character.toString(hashtag.charAt(1)));
hToken = this.getTokenForKey(hashValue);
}
Expand All @@ -90,18 +93,10 @@ public HostConnectionPool<CL> getPoolForOperation(BaseOperation<CL, ?> op, Strin
hostPool = tokenPools.get(hToken.getToken());
}

if (hashtag == null || hashtag.isEmpty()) {
if (hostPool == null) {
throw new NoAvailableHostsException(
if (hostPool == null) {
throw new NoAvailableHostsException(
"Could not find host connection pool for key: " + key + ", hash: " + tokenMapper.hash(key));
}
} else {
if (hostPool == null) {
throw new NoAvailableHostsException(
"Could not find host connection pool for hashtag: " + hashtag + ", hash: " + tokenMapper.hash(hashtag));
}
}

return hostPool;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -145,14 +145,14 @@ public void testParseJsonWithHastags() throws Exception {

List<Host> hostList = new ArrayList<Host>();

hostList.add(new Host("ec2-54-237-143-4.compute-1.amazonaws.com", 11211, "us-east-1d", Status.Up, "{}"));
hostList.add(new Host("ec2-50-17-65-2.compute-1.amazonaws.com", 11211, "us-east-1d", Status.Up, "{}"));
hostList.add(new Host("ec2-54-83-87-174.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up, "{}"));
hostList.add(new Host("ec2-54-81-138-73.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up, "{}"));
hostList.add(new Host("ec2-54-82-176-215.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up, "{}"));
hostList.add(new Host("ec2-54-82-83-115.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up, "{}"));
hostList.add(new Host("ec2-54-211-220-55.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up, "{}"));
hostList.add(new Host("ec2-54-80-65-203.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up, "{}"));
hostList.add(new Host("ec2-54-237-143-4.compute-1.amazonaws.com", 11211, "us-east-1d", Status.Up));
hostList.add(new Host("ec2-50-17-65-2.compute-1.amazonaws.com", 11211, "us-east-1d", Status.Up));
hostList.add(new Host("ec2-54-83-87-174.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up));
hostList.add(new Host("ec2-54-81-138-73.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up));
hostList.add(new Host("ec2-54-82-176-215.compute-1.amazonaws.com", 11211, "us-east-1c", Status.Up));
hostList.add(new Host("ec2-54-82-83-115.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up));
hostList.add(new Host("ec2-54-211-220-55.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up));
hostList.add(new Host("ec2-54-80-65-203.compute-1.amazonaws.com", 11211, "us-east-1e", Status.Up));

HttpEndpointBasedTokenMapSupplier tokenSupplier = new HttpEndpointBasedTokenMapSupplier("us-east-1d", 11211);

Expand Down
Loading

0 comments on commit 026c61a

Please sign in to comment.