Skip to content

Commit

Permalink
Support changed CLUSTER SLOTS #183
Browse files Browse the repository at this point in the history
  • Loading branch information
mp911de committed Jan 29, 2016
1 parent c4a817e commit 4b73166
Show file tree
Hide file tree
Showing 3 changed files with 180 additions and 12 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@
import java.io.Serializable;
import java.util.Collections;
import java.util.List;
import java.util.Set;

import com.google.common.collect.Lists;
import com.google.common.net.HostAndPort;
import com.lambdaworks.redis.RedisURI;
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;

/**
* Represents a range of slots together with its master and slaves.
Expand All @@ -18,9 +22,17 @@
public class ClusterSlotRange implements Serializable {
private int from;
private int to;

@Deprecated
private HostAndPort master;

private RedisClusterNode masterNode;

@Deprecated
private List<HostAndPort> slaves = Collections.emptyList();

private List<RedisClusterNode> slaveNodes = Collections.emptyList();

public ClusterSlotRange() {

}
Expand All @@ -32,18 +44,73 @@ public ClusterSlotRange() {
* @param to to slot
* @param master master for the slots, may be {@literal null}
* @param slaves list of slaves must not be {@literal null} but may be empty
* @deprecated Use {@link #ClusterSlotRange(int, int, RedisClusterNode, List)}
*/
@Deprecated
public ClusterSlotRange(int from, int to, HostAndPort master, List<HostAndPort> slaves) {

checkArgument(master != null, "master must not be null");
checkArgument(slaves != null, "slaves must not be null");

this.from = from;
this.to = to;
this.masterNode = toRedisClusterNode(master, null, Collections.singleton(RedisClusterNode.NodeFlag.MASTER));
this.slaveNodes = toRedisClusterNodes(slaves, null, Collections.singleton(RedisClusterNode.NodeFlag.SLAVE));
this.master = master;
this.slaves = slaves;
}

/**
* Constructs a {@link ClusterSlotRange}
*
* @param from from slot
* @param to to slot
* @param masterNode master for the slots, may be {@literal null}
* @param slaveNodes list of slaves must not be {@literal null} but may be empty
*/
public ClusterSlotRange(int from, int to, RedisClusterNode masterNode, List<RedisClusterNode> slaveNodes) {

checkArgument(masterNode != null, "masterNode must not be null");
checkArgument(slaveNodes != null, "slaveNodes must not be null");

this.from = from;
this.to = to;
this.master = toHostAndPort(masterNode);
this.slaves = toHostAndPorts(slaveNodes);
this.masterNode = masterNode;
this.slaveNodes = slaveNodes;
}

private HostAndPort toHostAndPort(RedisClusterNode redisClusterNode) {
RedisURI uri = redisClusterNode.getUri();
return HostAndPort.fromParts(uri.getHost(), uri.getPort());
}

private List<HostAndPort> toHostAndPorts(List<RedisClusterNode> nodes) {
List<HostAndPort> result = Lists.newArrayList();
for (RedisClusterNode node : nodes) {
result.add(toHostAndPort(node));
}
return result;
}

private RedisClusterNode toRedisClusterNode(HostAndPort hostAndPort, String slaveOf, Set<RedisClusterNode.NodeFlag> flags) {
RedisClusterNode redisClusterNode = new RedisClusterNode();
redisClusterNode.setUri(RedisURI
.create(hostAndPort.getHostText(), hostAndPort.getPortOrDefault(RedisURI.DEFAULT_REDIS_PORT)));
redisClusterNode.setSlaveOf(slaveOf);
redisClusterNode.setFlags(flags);
return redisClusterNode;
}

private List<RedisClusterNode> toRedisClusterNodes(List<HostAndPort> hostAndPorts, String slaveOf, Set<RedisClusterNode.NodeFlag> flags) {
List<RedisClusterNode> result = Lists.newArrayList();
for (HostAndPort hostAndPort : hostAndPorts) {
result.add(toRedisClusterNode(hostAndPort, slaveOf, flags));
}
return result;
}

public int getFrom() {
return from;
}
Expand All @@ -52,14 +119,40 @@ public int getTo() {
return to;
}

/**
* @deprecated Use {@link #getMasterNode()} to retrieve the {@code nodeId} and the {@code slaveOf} details.
* @return the master host and port
*/
@Deprecated
public HostAndPort getMaster() {
return master;
}

/**
* @deprecated Use {@link #getSlaveNodes()} to retrieve the {@code nodeId} and the {@code slaveOf} details.
* @return the master host and port
*/
@Deprecated
public List<HostAndPort> getSlaves() {
return slaves;
}

public RedisClusterNode getMasterNode() {
return masterNode;
}

public void setMasterNode(RedisClusterNode masterNode) {
this.masterNode = masterNode;
}

public List<RedisClusterNode> getSlaveNodes() {
return slaveNodes;
}

public void setSlaveNodes(List<RedisClusterNode> slaveNodes) {
this.slaveNodes = slaveNodes;
}

public void setFrom(int from) {
this.from = from;
}
Expand All @@ -85,8 +178,8 @@ public String toString() {
sb.append(getClass().getSimpleName());
sb.append(" [from=").append(from);
sb.append(", to=").append(to);
sb.append(", master=").append(master);
sb.append(", slaves=").append(slaves);
sb.append(", masterNode=").append(masterNode);
sb.append(", slaveNodes=").append(slaveNodes);
sb.append(']');
return sb.toString();
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,9 @@
import java.util.List;

import com.google.common.collect.Lists;
import com.google.common.net.HostAndPort;
import com.google.common.primitives.Ints;
import com.lambdaworks.redis.RedisURI;
import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;

/**
* Parser for redis <a href="http://redis.io/commands/cluster-slots">CLUSTER SLOTS</a> command output.
Expand Down Expand Up @@ -64,37 +65,50 @@ private static ClusterSlotRange parseRange(List<?> range) {

int from = Ints.checkedCast(getLongFromIterator(iterator, 0));
int to = Ints.checkedCast(getLongFromIterator(iterator, 0));
HostAndPort master = null;
RedisClusterNode master = null;

List<HostAndPort> slaves = Lists.newArrayList();
List<RedisClusterNode> slaves = Lists.newArrayList();
if (iterator.hasNext()) {
master = getHostAndPort(iterator);
master = getRedisClusterNode(iterator);
if(master != null) {
master.setFlags(Collections.singleton(RedisClusterNode.NodeFlag.MASTER));
}
}

while (iterator.hasNext()) {
HostAndPort slave = getHostAndPort(iterator);
RedisClusterNode slave = getRedisClusterNode(iterator);
if (slave != null) {
slave.setSlaveOf(master.getNodeId());
slave.setFlags(Collections.singleton(RedisClusterNode.NodeFlag.SLAVE));
slaves.add(slave);
}
}

return new ClusterSlotRange(from, to, master, Collections.unmodifiableList(slaves));
}

private static HostAndPort getHostAndPort(Iterator<?> iterator) {
private static RedisClusterNode getRedisClusterNode(Iterator<?> iterator) {
Object element = iterator.next();
if (element instanceof List) {
List<?> hostAndPortList = (List<?>) element;
if (hostAndPortList.size() != 2) {
if (hostAndPortList.size() < 2) {
return null;
}

Iterator<?> hostAndPortIterator = hostAndPortList.iterator();
String host = (String) hostAndPortIterator.next();
int port = Ints.checkedCast(getLongFromIterator(hostAndPortIterator, 0));
HostAndPort hostAndPort = HostAndPort.fromParts(host, port);
String nodeId;

RedisClusterNode redisClusterNode = new RedisClusterNode();
redisClusterNode.setUri(RedisURI.create(host, port));

if (hostAndPortIterator.hasNext()) {
nodeId = (String) hostAndPortIterator.next();
redisClusterNode.setNodeId(nodeId);
}

return hostAndPort;
return redisClusterNode;

}
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

import java.util.List;

import com.lambdaworks.redis.cluster.models.partitions.RedisClusterNode;
import org.junit.Test;

import com.google.common.collect.ImmutableList;
Expand Down Expand Up @@ -39,10 +40,71 @@ public void testParse() throws Exception {
assertThat(result).hasSize(1);

assertThat(result.get(0).getMaster()).isNotNull();
assertThat(result.get(0).getMasterNode()).isNotNull();
}

@Test
public void testParseWithSlave() throws Exception {
List<?> list = ImmutableList.of(Lists.newArrayList("0", "1", Lists.newArrayList("1", "2", "nodeId1"), Lists.newArrayList("1", 2, "nodeId2")));
List<ClusterSlotRange> result = ClusterSlotsParser.parse(list);
assertThat(result).hasSize(1);
ClusterSlotRange clusterSlotRange = result.get(0);

assertThat(clusterSlotRange.getMaster()).isNotNull();
assertThat(clusterSlotRange.getMaster().getHostText()).isEqualTo("1");
assertThat(clusterSlotRange.getMaster().getPort()).isEqualTo(2);

RedisClusterNode masterNode = clusterSlotRange.getMasterNode();
assertThat(masterNode).isNotNull();
assertThat(masterNode.getNodeId()).isEqualTo("nodeId1");
assertThat(masterNode.getUri().getHost()).isEqualTo("1");
assertThat(masterNode.getUri().getPort()).isEqualTo(2);
assertThat(masterNode.getFlags()).contains(RedisClusterNode.NodeFlag.MASTER);

assertThat(clusterSlotRange.getSlaves()).hasSize(1);
assertThat(clusterSlotRange.getSlaveNodes()).hasSize(1);

HostAndPort slave = clusterSlotRange.getSlaves().get(0);
assertThat(slave.getHostText()).isEqualTo("1");
assertThat(slave.getPort()).isEqualTo(2);

RedisClusterNode slaveNode = clusterSlotRange.getSlaveNodes().get(0);

assertThat(slaveNode.getNodeId()).isEqualTo("nodeId2");
assertThat(slaveNode.getSlaveOf()).isEqualTo("nodeId1");
assertThat(slaveNode.getFlags()).contains(RedisClusterNode.NodeFlag.SLAVE);
}

@Test
public void testHostAndPortConstructor() throws Exception {

ClusterSlotRange clusterSlotRange = new ClusterSlotRange(100,200,HostAndPort.fromParts("1", 2), ImmutableList.of(
HostAndPort.fromParts("1", 2)));

RedisClusterNode masterNode = clusterSlotRange.getMasterNode();
assertThat(masterNode).isNotNull();
assertThat(masterNode.getNodeId()).isNull();
assertThat(masterNode.getUri().getHost()).isEqualTo("1");
assertThat(masterNode.getUri().getPort()).isEqualTo(2);
assertThat(masterNode.getFlags()).contains(RedisClusterNode.NodeFlag.MASTER);

assertThat(clusterSlotRange.getSlaves()).hasSize(1);
assertThat(clusterSlotRange.getSlaveNodes()).hasSize(1);

HostAndPort slave = clusterSlotRange.getSlaves().get(0);
assertThat(slave.getHostText()).isEqualTo("1");
assertThat(slave.getPort()).isEqualTo(2);

RedisClusterNode slaveNode = clusterSlotRange.getSlaveNodes().get(0);

assertThat(slaveNode.getNodeId()).isNull();
assertThat(slaveNode.getSlaveOf()).isNull();
assertThat(slaveNode.getFlags()).contains(RedisClusterNode.NodeFlag.SLAVE);

}

@Test
public void testParseWithSlaveAndNodeIds() throws Exception {
List<?> list = ImmutableList.of(Lists.newArrayList("0", "1", Lists.newArrayList("1", "2"), Lists.newArrayList("1", 2)));
List<ClusterSlotRange> result = ClusterSlotsParser.parse(list);
assertThat(result).hasSize(1);
Expand Down Expand Up @@ -72,6 +134,5 @@ public void testModel() throws Exception {
range.setMaster(HostAndPort.fromHost("localhost"));

assertThat(range.toString()).contains(ClusterSlotRange.class.getSimpleName());

}
}

0 comments on commit 4b73166

Please sign in to comment.