diff --git a/Makefile b/Makefile index 3606f06..30a8b04 100644 --- a/Makefile +++ b/Makefile @@ -101,9 +101,9 @@ start: echo "$$REDIS3_CONF" | redis-server - echo "$$REDIS4_CONF" | redis-server - echo "$$REDIS5_CONF" | redis-server - - echo "$$REDIS_SENTINEL1" | redis-server - --sentinel - echo "$$REDIS_SENTINEL2" | redis-server - --sentinel - echo "$$REDIS_SENTINEL3" | redis-server - --sentinel + echo "$$REDIS_SENTINEL1" > /tmp/sentinel1.conf && redis-server /tmp/sentinel1.conf --sentinel + echo "$$REDIS_SENTINEL2" > /tmp/sentinel2.conf && redis-server /tmp/sentinel2.conf --sentinel + echo "$$REDIS_SENTINEL3" > /tmp/sentinel3.conf && redis-server /tmp/sentinel3.conf --sentinel stop: kill `cat /tmp/redis1.pid` diff --git a/src/main/java/redis/clients/jedis/Client.java b/src/main/java/redis/clients/jedis/Client.java index 8db267d..9c97e38 100644 --- a/src/main/java/redis/clients/jedis/Client.java +++ b/src/main/java/redis/clients/jedis/Client.java @@ -752,11 +752,6 @@ public class Client extends BinaryClient implements Commands { sentinel(arg); } - public void sentinel(final String cmd, String arg1, int arg2) { - sentinel(SafeEncoder.encode(cmd), SafeEncoder.encode(arg1), - toByteArray(arg2)); - } - public void dump(final String key) { dump(SafeEncoder.encode(key)); } diff --git a/src/main/java/redis/clients/jedis/HostAndPort.java b/src/main/java/redis/clients/jedis/HostAndPort.java new file mode 100644 index 0000000..488eac3 --- /dev/null +++ b/src/main/java/redis/clients/jedis/HostAndPort.java @@ -0,0 +1,39 @@ +package redis.clients.jedis; + +public class HostAndPort { + private String host; + private int port; + + public HostAndPort(String host, int port) { + this.host = host; + this.port = port; + } + + public String getHost() { + return host; + } + + public int getPort() { + return port; + } + + @Override + public boolean equals(Object obj) { + if (obj instanceof HostAndPort) { + HostAndPort hp = (HostAndPort) obj; + + // localhost and 127.0.0.1 is same + return port == hp.port && + (host.equals(hp.host) || + (host.equals("localhost") && hp.host.equals("127.0.0.1")) || + (host.equals("127.0.0.1") && hp.host.equals("localhost")) ); + } + + return false; + } + + @Override + public String toString() { + return host + ":" + port; + } +} diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index 6d0c986..23cfd3d 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -2997,27 +2997,6 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand return slaves; } - /** - *
-     * redis 127.0.0.1:26381> SENTINEL is-master-down-by-addr 127.0.0.1 1
-     * 1) (integer) 0
-     * 2) "?"
-     * redis 127.0.0.1:26381> SENTINEL is-master-down-by-addr 127.0.0.1 6379
-     * 1) (integer) 0
-     * 2) "aaef11fbb2712346a386078c7f9834e72ed51e96"
-     * 
- * - * @return Long followed by the String (runid) - */ - @SuppressWarnings("unchecked") - public List sentinelIsMasterDownByAddr(String host, - int port) { - client.sentinel(Protocol.SENTINEL_IS_MASTER_DOWN_BY_ADDR, host, port); - final List reply = client.getObjectMultiBulkReply(); - return Arrays.asList(BuilderFactory.LONG.build(reply.get(0)), - BuilderFactory.STRING.build(reply.get(1))); - } - public byte[] dump(final String key) { checkIsInMulti(); client.dump(key); diff --git a/src/main/java/redis/clients/jedis/JedisSentinelPool.java b/src/main/java/redis/clients/jedis/JedisSentinelPool.java index 2761c90..e4c6e3b 100644 --- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java +++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java @@ -82,25 +82,6 @@ public class JedisSentinelPool extends Pool { returnResourceObject(resource); } - private class HostAndPort { - String host; - int port; - - @Override - public boolean equals(Object obj) { - if (obj instanceof HostAndPort) { - HostAndPort hp = (HostAndPort) obj; - return port == hp.port && host.equals(hp.host); - } - return false; - } - - @Override - public String toString() { - return host + ":" + port; - } - } - private volatile HostAndPort currentHostMaster; public void destroy() { @@ -119,7 +100,7 @@ public class JedisSentinelPool extends Pool { if (!master.equals(currentHostMaster)) { currentHostMaster = master; log.info("Created JedisPool to master at " + master); - initPool(poolConfig, new JedisFactory(master.host, master.port, + initPool(poolConfig, new JedisFactory(master.getHost(), master.getPort(), timeout, password, database)); } } @@ -142,7 +123,7 @@ public class JedisSentinelPool extends Pool { log.fine("Connecting to Sentinel " + hap); try { - Jedis jedis = new Jedis(hap.host, hap.port); + Jedis jedis = new Jedis(hap.getHost(), hap.getPort()); if (master == null) { master = toHostAndPort(jedis @@ -173,7 +154,7 @@ public class JedisSentinelPool extends Pool { final HostAndPort hap = toHostAndPort(Arrays.asList(sentinel .split(":"))); MasterListener masterListener = new MasterListener(masterName, - hap.host, hap.port); + hap.getHost(), hap.getPort()); masterListeners.add(masterListener); masterListener.start(); } @@ -182,10 +163,10 @@ public class JedisSentinelPool extends Pool { } private HostAndPort toHostAndPort(List getMasterAddrByNameResult) { - final HostAndPort hap = new HostAndPort(); - hap.host = getMasterAddrByNameResult.get(0); - hap.port = Integer.parseInt(getMasterAddrByNameResult.get(1)); - return hap; + String host = getMasterAddrByNameResult.get(0); + int port = Integer.parseInt(getMasterAddrByNameResult.get(1)); + + return new HostAndPort(host, port); } protected class JedisPubSubAdapter extends JedisPubSub { diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index db3d915..f85c324 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -29,7 +29,6 @@ public final class Protocol { public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name"; public static final String SENTINEL_RESET = "reset"; public static final String SENTINEL_SLAVES = "slaves"; - public static final String SENTINEL_IS_MASTER_DOWN_BY_ADDR = "is-master-down-by-addr"; private Protocol() { // this prevent the class from instantiation diff --git a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java index 648725e..03e421e 100644 --- a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java +++ b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java @@ -3,52 +3,37 @@ package redis.clients.jedis.tests; import java.util.ArrayList; import java.util.List; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Protocol; public class HostAndPortUtil { - private static List redisHostAndPortList = new ArrayList(); - private static List sentinelHostAndPortList = new ArrayList(); + private static List redisHostAndPortList = new ArrayList(); + private static List sentinelHostAndPortList = new ArrayList(); static { - HostAndPort defaulthnp1 = new HostAndPort(); - defaulthnp1.host = "localhost"; - defaulthnp1.port = Protocol.DEFAULT_PORT; + HostAndPort defaulthnp1 = new HostAndPort("localhost", Protocol.DEFAULT_PORT); redisHostAndPortList.add(defaulthnp1); - HostAndPort defaulthnp2 = new HostAndPort(); - defaulthnp2.host = "localhost"; - defaulthnp2.port = Protocol.DEFAULT_PORT + 1; + HostAndPort defaulthnp2 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 1); redisHostAndPortList.add(defaulthnp2); - HostAndPort defaulthnp3 = new HostAndPort(); - defaulthnp3.host = "localhost"; - defaulthnp3.port = Protocol.DEFAULT_PORT + 2; + HostAndPort defaulthnp3 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 2); redisHostAndPortList.add(defaulthnp3); - HostAndPort defaulthnp4 = new HostAndPort(); - defaulthnp4.host = "localhost"; - defaulthnp4.port = Protocol.DEFAULT_PORT + 3; + HostAndPort defaulthnp4 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 3); redisHostAndPortList.add(defaulthnp4); - HostAndPort defaulthnp5 = new HostAndPort(); - defaulthnp5.host = "localhost"; - defaulthnp5.port = Protocol.DEFAULT_PORT + 4; + HostAndPort defaulthnp5 = new HostAndPort("localhost", Protocol.DEFAULT_PORT + 4); redisHostAndPortList.add(defaulthnp5); - HostAndPort defaulthnp6 = new HostAndPort(); - defaulthnp6.host = "localhost"; - defaulthnp6.port = Protocol.DEFAULT_SENTINEL_PORT; + HostAndPort defaulthnp6 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT); sentinelHostAndPortList.add(defaulthnp6); - HostAndPort defaulthnp7 = new HostAndPort(); - defaulthnp7.host = "localhost"; - defaulthnp7.port = Protocol.DEFAULT_SENTINEL_PORT + 1; + HostAndPort defaulthnp7 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 1); sentinelHostAndPortList.add(defaulthnp7); - HostAndPort defaulthnp8 = new HostAndPort(); - defaulthnp8.host = "localhost"; - defaulthnp8.port = Protocol.DEFAULT_SENTINEL_PORT + 2; + HostAndPort defaulthnp8 = new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 2); sentinelHostAndPortList.add(defaulthnp8); String envRedisHosts = System.getProperty("redis-hosts"); @@ -66,24 +51,22 @@ public class HostAndPortUtil { if (null != hostDefs && 2 <= hostDefs.length) { - List envHostsAndPorts = new ArrayList(hostDefs.length); + List envHostsAndPorts = new ArrayList(hostDefs.length); for (String hostDef : hostDefs) { String[] hostAndPort = hostDef.split(":"); if (null != hostAndPort && 2 == hostAndPort.length) { + String host = hostAndPort[0]; + int port = Protocol.DEFAULT_PORT; - HostAndPort hnp = new HostAndPort(); - hnp.host = hostAndPort[0]; - - try { - hnp.port = Integer.parseInt(hostAndPort[1]); + try { + port = Integer.parseInt(hostAndPort[1]); } catch (final NumberFormatException nfe) { - hnp.port = Protocol.DEFAULT_PORT; - } - - envHostsAndPorts.add(hnp); + } + + envHostsAndPorts.add(new HostAndPort(host, port)); } } @@ -102,13 +85,4 @@ public class HostAndPortUtil { return sentinelHostAndPortList; } - public static class HostAndPort { - public String host; - public int port; - - @Override - public String toString() { - return host + ":" + port; - } - } } diff --git a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java index 286d681..652de92 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java @@ -7,69 +7,70 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.junit.Assert; import org.junit.Test; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class JedisPoolTest extends Assert { private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @Test public void checkConnections() { - JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port, 2000); - Jedis jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.set("foo", "bar"); - assertEquals("bar", jedis.get("foo")); - pool.returnResource(jedis); - pool.destroy(); + JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort(), 2000); + Jedis jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.set("foo", "bar"); + assertEquals("bar", jedis.get("foo")); + pool.returnResource(jedis); + pool.destroy(); } @Test public void checkConnectionWithDefaultPort() { - JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port); - Jedis jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.set("foo", "bar"); - assertEquals("bar", jedis.get("foo")); - pool.returnResource(jedis); - pool.destroy(); + JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort()); + Jedis jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.set("foo", "bar"); + assertEquals("bar", jedis.get("foo")); + pool.returnResource(jedis); + pool.destroy(); } @Test public void checkJedisIsReusedWhenReturned() { - JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port); - Jedis jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.set("foo", "0"); - pool.returnResource(jedis); - jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.incr("foo"); - pool.returnResource(jedis); - pool.destroy(); + JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort()); + Jedis jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.set("foo", "0"); + pool.returnResource(jedis); + + jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.incr("foo"); + pool.returnResource(jedis); + pool.destroy(); } @Test public void checkPoolRepairedWhenJedisIsBroken() { - JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port); - Jedis jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.quit(); - pool.returnBrokenResource(jedis); + JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort()); + Jedis jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.quit(); + pool.returnBrokenResource(jedis); - jedis = pool.getResource(); - jedis.auth("foobared"); - jedis.incr("foo"); - pool.returnResource(jedis); - pool.destroy(); + jedis = pool.getResource(); + jedis.auth("foobared"); + jedis.incr("foo"); + pool.returnResource(jedis); + pool.destroy(); } @Test(expected = JedisConnectionException.class) @@ -77,7 +78,7 @@ public class JedisPoolTest extends Assert { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); - JedisPool pool = new JedisPool(config, hnp.host, hnp.port); + JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort()); Jedis jedis = pool.getResource(); jedis.auth("foobared"); jedis.set("foo", "0"); @@ -91,7 +92,7 @@ public class JedisPoolTest extends Assert { public void securePool() { JedisPoolConfig config = new JedisPoolConfig(); config.setTestOnBorrow(true); - JedisPool pool = new JedisPool(config, hnp.host, hnp.port, 2000, + JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, "foobared"); Jedis jedis = pool.getResource(); jedis.set("foo", "bar"); @@ -101,16 +102,16 @@ public class JedisPoolTest extends Assert { @Test public void nonDefaultDatabase() { - JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port, 2000, "foobared"); + JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort(), 2000, "foobared"); Jedis jedis0 = pool0.getResource(); jedis0.set("foo", "bar"); assertEquals("bar", jedis0.get("foo")); pool0.returnResource(jedis0); pool0.destroy(); - JedisPool pool1 = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port, 2000, "foobared", 1); + JedisPool pool1 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort(), 2000, "foobared", 1); Jedis jedis1 = pool1.getResource(); assertNull(jedis1.get("foo")); pool1.returnResource(jedis1); @@ -144,8 +145,8 @@ public class JedisPoolTest extends Assert { @Test public void selectDatabaseOnActivation() { - JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port, 2000, "foobared"); + JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort(), 2000, "foobared"); Jedis jedis0 = pool.getResource(); assertEquals(0L, jedis0.getDB().longValue()); @@ -165,8 +166,8 @@ public class JedisPoolTest extends Assert { @Test public void customClientName() { - JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.host, - hnp.port, 2000, "foobared", 0, "my_shiny_client_name"); + JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.getHost(), + hnp.getPort(), 2000, "foobared", 0, "my_shiny_client_name"); Jedis jedis = pool0.getResource(); diff --git a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java index 2487c8d..97a02ed 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java @@ -1,6 +1,8 @@ package redis.clients.jedis.tests; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; @@ -8,11 +10,13 @@ import org.junit.Before; import org.junit.Test; import redis.clients.jedis.DebugParams; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisSentinelPool; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; +import redis.clients.jedis.tests.utils.JedisSentinelTestUtil; public class JedisSentinelPoolTest extends JedisTestBase { + private static final String MASTER_NAME = "mymaster"; protected static HostAndPort master = HostAndPortUtil.getRedisServers() .get(2); @@ -28,8 +32,8 @@ public class JedisSentinelPoolTest extends JedisTestBase { protected static Jedis masterJedis; protected static Jedis slaveJedis1; protected static Jedis slaveJedis2; - - protected static int slaveCount = 0; + protected static Jedis sentinelJedis1; + protected static Jedis sentinelJedis2; protected Set sentinels = new HashSet(); @@ -37,32 +41,36 @@ public class JedisSentinelPoolTest extends JedisTestBase { public void setUp() throws Exception { // set up master and slaves - masterJedis = new Jedis(master.host, master.port); + masterJedis = new Jedis(master.getHost(), master.getPort()); masterJedis.auth("foobared"); masterJedis.slaveofNoOne(); - slaveJedis1 = new Jedis(slave1.host, slave1.port); + slaveJedis1 = new Jedis(slave1.getHost(), slave1.getPort()); slaveJedis1.auth("foobared"); - slaveJedis1.slaveof(master.host, master.port); - slaveCount++; + slaveJedis1.slaveof(master.getHost(), master.getPort()); - slaveJedis2 = new Jedis(slave2.host, slave2.port); + slaveJedis2 = new Jedis(slave2.getHost(), slave2.getPort()); slaveJedis2.auth("foobared"); - slaveJedis2.slaveof(master.host, master.port); - slaveCount++; + slaveJedis2.slaveof(master.getHost(), master.getPort()); sentinels.add(sentinel1.toString()); sentinels.add(sentinel2.toString()); - // FIXME: The following allows the master/slave relationship to - // be established, and let sentinels know about this relationship. - // We can do this more elegantly. - Thread.sleep(10000); + List slaves = new ArrayList(); + slaves.add(slave1); + slaves.add(slave2); + + JedisSentinelTestUtil.waitForSentinelRecognizeRedisReplication( + sentinel1, MASTER_NAME, master, slaves); + JedisSentinelTestUtil.waitForSentinelRecognizeRedisReplication( + sentinel2, MASTER_NAME, master, slaves); + + // No need to wait for sentinels to recognize each other } @Test public void ensureSafeTwiceFailover() throws InterruptedException { - JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels, + JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, new GenericObjectPoolConfig(), 1000, "foobared", 2); // perform failover @@ -77,6 +85,8 @@ public class JedisSentinelPoolTest extends JedisTestBase { private void doSegFaultMaster(JedisSentinelPool pool) throws InterruptedException { + HostAndPort oldMaster = pool.getCurrentHostMaster(); + // jedis connection should be master Jedis jedis = pool.getResource(); assertEquals("PONG", jedis.ping()); @@ -86,14 +96,40 @@ public class JedisSentinelPoolTest extends JedisTestBase { } catch (Exception e) { } - // wait for the sentinel to promote a master - // FIXME: we can query the sentinel and sleep - // right until the master is promoted - Thread.sleep(35000); + waitForFailover(pool, oldMaster); jedis = pool.getResource(); assertEquals("PONG", jedis.ping()); assertEquals("foobared", jedis.configGet("requirepass").get(1)); assertEquals(2, jedis.getDB().intValue()); } + + private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster) + throws InterruptedException { + HostAndPort newMaster = JedisSentinelTestUtil.waitForNewPromotedMaster( + sentinel1, MASTER_NAME, oldMaster); + JedisSentinelTestUtil.waitForNewPromotedMaster(sentinel2, MASTER_NAME, + oldMaster); + JedisSentinelTestUtil.waitForSentinelsRecognizeEachOthers(); + waitForJedisSentinelPoolRecognizeNewMaster(pool, newMaster); + } + + private void waitForJedisSentinelPoolRecognizeNewMaster( + JedisSentinelPool pool, HostAndPort newMaster) + throws InterruptedException { + + while (true) { + String host = pool.getCurrentHostMaster().getHost(); + int port = pool.getCurrentHostMaster().getPort(); + + if (host.equals(newMaster.getHost()) && port == newMaster.getPort()) + break; + + System.out + .println("JedisSentinelPool's master is not yet changed, sleep..."); + + Thread.sleep(1000); + } + } + } diff --git a/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java index c2369c7..3e5cfdf 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java @@ -1,9 +1,6 @@ package redis.clients.jedis.tests; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertFalse; -import static org.junit.Assert.assertTrue; - +import java.util.ArrayList; import java.util.List; import java.util.Map; @@ -11,25 +8,42 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; +import redis.clients.jedis.tests.utils.JedisSentinelTestUtil; -public class JedisSentinelTest { +public class JedisSentinelTest extends JedisTestBase { private static final String MASTER_NAME = "mymaster"; + protected static HostAndPort master = HostAndPortUtil.getRedisServers() + .get(0); + protected static HostAndPort slave = HostAndPortUtil.getRedisServers().get( + 1); + protected static HostAndPort sentinel = HostAndPortUtil + .getSentinelServers().get(0); + + protected static Jedis masterJedis; + protected static Jedis slaveJedis; + protected static Jedis sentinelJedis; + @Before public void setup() throws InterruptedException { - Jedis j = new Jedis("localhost", 6380); - j.auth("foobared"); - j.configSet("masterauth", "foobared"); - j.slaveof("localhost", 6379); - // TODO: The sleep is to give time to the slave to synchronize with the - // master and also let know the sentinels about this new topology. We - // should find a better way to do this. - Thread.sleep(10000); + masterJedis = new Jedis(master.getHost(), master.getPort()); + + slaveJedis = new Jedis(slave.getHost(), slave.getPort()); + slaveJedis.auth("foobared"); + slaveJedis.configSet("masterauth", "foobared"); + slaveJedis.slaveof(master.getHost(), master.getPort()); + + List slaves = new ArrayList(); + slaves.add(slave); + + JedisSentinelTestUtil.waitForSentinelRecognizeRedisReplication( + sentinel, MASTER_NAME, master, slaves); } @After - public void clear() { + public void clear() throws InterruptedException { Jedis j = new Jedis("localhost", 6380); j.auth("foobared"); j.slaveofNoOne(); @@ -52,18 +66,8 @@ public class JedisSentinelTest { assertTrue(slaves.size() > 0); assertEquals("6379", slaves.get(0).get("master-port")); - List isMasterDownByAddr = j - .sentinelIsMasterDownByAddr("127.0.0.1", 6379); - assertEquals(Long.valueOf(0), (Long) isMasterDownByAddr.get(0)); - assertFalse("?".equals(isMasterDownByAddr.get(1))); - - isMasterDownByAddr = j.sentinelIsMasterDownByAddr("127.0.0.1", 1); - assertEquals(Long.valueOf(0), (Long) isMasterDownByAddr.get(0)); - assertTrue("?".equals(isMasterDownByAddr.get(1))); - // DO NOT RE-RUN TEST TOO FAST, RESET TAKES SOME TIME TO... RESET assertEquals(Long.valueOf(1), j.sentinelReset(masterName)); assertEquals(Long.valueOf(0), j.sentinelReset("woof" + masterName)); - } } diff --git a/src/test/java/redis/clients/jedis/tests/PipeliningTest.java b/src/test/java/redis/clients/jedis/tests/PipeliningTest.java index c5ab782..1fe063c 100755 --- a/src/test/java/redis/clients/jedis/tests/PipeliningTest.java +++ b/src/test/java/redis/clients/jedis/tests/PipeliningTest.java @@ -1,14 +1,24 @@ package redis.clients.jedis.tests; +import java.io.UnsupportedEncodingException; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Set; +import java.util.UUID; + import org.junit.Assert; import org.junit.Before; import org.junit.Test; -import redis.clients.jedis.*; -import redis.clients.jedis.exceptions.JedisDataException; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; -import java.io.UnsupportedEncodingException; -import java.util.*; +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.Pipeline; +import redis.clients.jedis.PipelineBlock; +import redis.clients.jedis.Response; +import redis.clients.jedis.Tuple; +import redis.clients.jedis.exceptions.JedisDataException; public class PipeliningTest extends Assert { private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @@ -17,7 +27,7 @@ public class PipeliningTest extends Assert { @Before public void setUp() throws Exception { - jedis = new Jedis(hnp.host, hnp.port, 500); + jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500); jedis.connect(); jedis.auth("foobared"); jedis.flushAll(); diff --git a/src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java b/src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java index 0f2e183..bf9b2bd 100644 --- a/src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java +++ b/src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java @@ -15,6 +15,7 @@ import java.util.UUID; import org.junit.Before; import org.junit.Test; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.Response; @@ -24,32 +25,36 @@ import redis.clients.jedis.Tuple; import redis.clients.jedis.exceptions.JedisDataException; public class ShardedJedisPipelineTest { - private static HostAndPortUtil.HostAndPort redis1 = HostAndPortUtil - .getRedisServers().get(0); - private static HostAndPortUtil.HostAndPort redis2 = HostAndPortUtil - .getRedisServers().get(1); + + private static HostAndPort redis1 = HostAndPortUtil.getRedisServers() + .get(0); + private static HostAndPort redis2 = HostAndPortUtil.getRedisServers() + .get(1); private ShardedJedis jedis; @Before public void setUp() throws Exception { - Jedis jedis = new Jedis(redis1.host, redis1.port); + Jedis jedis = new Jedis(redis1.getHost(), redis1.getPort()); jedis.auth("foobared"); jedis.flushAll(); jedis.disconnect(); - jedis = new Jedis(redis2.host, redis2.port); + jedis = new Jedis(redis2.getHost(), redis2.getPort()); jedis.auth("foobared"); jedis.flushAll(); jedis.disconnect(); - JedisShardInfo shardInfo1 = new JedisShardInfo(redis1.host, redis1.port); - JedisShardInfo shardInfo2 = new JedisShardInfo(redis2.host, redis2.port); + JedisShardInfo shardInfo1 = new JedisShardInfo(redis1.getHost(), + redis1.getPort()); + JedisShardInfo shardInfo2 = new JedisShardInfo(redis2.getHost(), + redis2.getPort()); shardInfo1.setPassword("foobared"); shardInfo2.setPassword("foobared"); List shards = new ArrayList(); shards.add(shardInfo1); shards.add(shardInfo2); this.jedis = new ShardedJedis(shards); + } @Test diff --git a/src/test/java/redis/clients/jedis/tests/ShardedJedisPoolTest.java b/src/test/java/redis/clients/jedis/tests/ShardedJedisPoolTest.java index fbb078e..35d7c54 100644 --- a/src/test/java/redis/clients/jedis/tests/ShardedJedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/ShardedJedisPoolTest.java @@ -10,12 +10,12 @@ import org.junit.Assert; import org.junit.Before; import org.junit.Test; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPool; import redis.clients.jedis.exceptions.JedisConnectionException; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class ShardedJedisPoolTest extends Assert { private static HostAndPort redis1 = HostAndPortUtil.getRedisServers() @@ -28,8 +28,8 @@ public class ShardedJedisPoolTest extends Assert { @Before public void startUp() { shards = new ArrayList(); - shards.add(new JedisShardInfo(redis1.host, redis1.port)); - shards.add(new JedisShardInfo(redis2.host, redis2.port)); + shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); + shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.get(0).setPassword("foobared"); shards.get(1).setPassword("foobared"); Jedis j = new Jedis(shards.get(0)); @@ -40,6 +40,7 @@ public class ShardedJedisPoolTest extends Assert { j.connect(); j.flushAll(); j.disconnect(); + } @Test @@ -97,7 +98,7 @@ public class ShardedJedisPoolTest extends Assert { GenericObjectPoolConfig config = new GenericObjectPoolConfig(); config.setMaxTotal(1); config.setBlockWhenExhausted(false); - + ShardedJedisPool pool = new ShardedJedisPool(config, shards); ShardedJedis jedis = pool.getResource(); diff --git a/src/test/java/redis/clients/jedis/tests/ShardedJedisTest.java b/src/test/java/redis/clients/jedis/tests/ShardedJedisTest.java index e04a998..73532c7 100644 --- a/src/test/java/redis/clients/jedis/tests/ShardedJedisTest.java +++ b/src/test/java/redis/clients/jedis/tests/ShardedJedisTest.java @@ -6,12 +6,12 @@ import java.util.List; import org.junit.Assert; import org.junit.Test; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.Protocol; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedisPipeline; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; import redis.clients.util.Hashing; import redis.clients.util.SafeEncoder; import redis.clients.util.Sharded; @@ -41,8 +41,8 @@ public class ShardedJedisTest extends Assert { @Test public void checkSharding() { List shards = new ArrayList(); - shards.add(new JedisShardInfo(redis1.host, redis1.port)); - shards.add(new JedisShardInfo(redis2.host, redis2.port)); + shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); + shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); ShardedJedis jedis = new ShardedJedis(shards); List keys = getKeysDifferentShard(jedis); JedisShardInfo s1 = jedis.getShardInfo(keys.get(0)); @@ -53,10 +53,10 @@ public class ShardedJedisTest extends Assert { @Test public void trySharding() { List shards = new ArrayList(); - JedisShardInfo si = new JedisShardInfo(redis1.host, redis1.port); + JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort()); si.setPassword("foobared"); shards.add(si); - si = new JedisShardInfo(redis2.host, redis2.port); + si = new JedisShardInfo(redis2.getHost(), redis2.getPort()); si.setPassword("foobared"); shards.add(si); ShardedJedis jedis = new ShardedJedis(shards); @@ -80,10 +80,10 @@ public class ShardedJedisTest extends Assert { @Test public void tryShardingWithMurmure() { List shards = new ArrayList(); - JedisShardInfo si = new JedisShardInfo(redis1.host, redis1.port); + JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort()); si.setPassword("foobared"); shards.add(si); - si = new JedisShardInfo(redis2.host, redis2.port); + si = new JedisShardInfo(redis2.getHost(), redis2.getPort()); si.setPassword("foobared"); shards.add(si); ShardedJedis jedis = new ShardedJedis(shards, Hashing.MURMUR_HASH); @@ -107,8 +107,8 @@ public class ShardedJedisTest extends Assert { @Test public void checkKeyTags() { List shards = new ArrayList(); - shards.add(new JedisShardInfo(redis1.host, redis1.port)); - shards.add(new JedisShardInfo(redis2.host, redis2.port)); + shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); + shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); ShardedJedis jedis = new ShardedJedis(shards, ShardedJedis.DEFAULT_KEY_TAG_PATTERN); @@ -143,8 +143,8 @@ public class ShardedJedisTest extends Assert { @Test public void shardedPipeline() { List shards = new ArrayList(); - shards.add(new JedisShardInfo(redis1.host, redis1.port)); - shards.add(new JedisShardInfo(redis2.host, redis2.port)); + shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); + shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.get(0).setPassword("foobared"); shards.get(1).setPassword("foobared"); ShardedJedis jedis = new ShardedJedis(shards); diff --git a/src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java b/src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java index 8f944f4..9ce403d 100644 --- a/src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java +++ b/src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java @@ -4,9 +4,9 @@ import java.io.IOException; import java.net.UnknownHostException; import java.util.Calendar; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class GetSetBenchmark { private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @@ -14,7 +14,7 @@ public class GetSetBenchmark { public static void main(String[] args) throws UnknownHostException, IOException { - Jedis jedis = new Jedis(hnp.host, hnp.port); + Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort()); jedis.connect(); jedis.auth("foobared"); jedis.flushAll(); diff --git a/src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java b/src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java index 95a7991..4783754 100644 --- a/src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java +++ b/src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java @@ -7,11 +7,11 @@ import java.util.Calendar; import java.util.Collection; import java.util.List; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class HashingBenchmark { private static HostAndPort hnp1 = HostAndPortUtil.getRedisServers().get(0); @@ -21,10 +21,10 @@ public class HashingBenchmark { public static void main(String[] args) throws UnknownHostException, IOException { List shards = new ArrayList(); - JedisShardInfo shard = new JedisShardInfo(hnp1.host, hnp1.port); + JedisShardInfo shard = new JedisShardInfo(hnp1.getHost(), hnp1.getPort()); shard.setPassword("foobared"); shards.add(shard); - shard = new JedisShardInfo(hnp2.host, hnp2.port); + shard = new JedisShardInfo(hnp2.getHost(), hnp2.getPort()); shard.setPassword("foobared"); shards.add(shard); ShardedJedis jedis = new ShardedJedis(shards); diff --git a/src/test/java/redis/clients/jedis/tests/benchmark/PipelinedGetSetBenchmark.java b/src/test/java/redis/clients/jedis/tests/benchmark/PipelinedGetSetBenchmark.java index ae2f024..f8c41d7 100644 --- a/src/test/java/redis/clients/jedis/tests/benchmark/PipelinedGetSetBenchmark.java +++ b/src/test/java/redis/clients/jedis/tests/benchmark/PipelinedGetSetBenchmark.java @@ -4,10 +4,10 @@ import java.io.IOException; import java.net.UnknownHostException; import java.util.Calendar; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.Pipeline; import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class PipelinedGetSetBenchmark { private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @@ -15,7 +15,7 @@ public class PipelinedGetSetBenchmark { public static void main(String[] args) throws UnknownHostException, IOException { - Jedis jedis = new Jedis(hnp.host, hnp.port); + Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort()); jedis.connect(); jedis.auth("foobared"); jedis.flushAll(); diff --git a/src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java b/src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java index 224f004..095ee5b 100644 --- a/src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java +++ b/src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java @@ -6,17 +6,17 @@ import java.util.concurrent.atomic.AtomicInteger; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.Jedis; import redis.clients.jedis.JedisPool; import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class PoolBenchmark { private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); private static final int TOTAL_OPERATIONS = 100000; public static void main(String[] args) throws Exception { - Jedis j = new Jedis(hnp.host, hnp.port); + Jedis j = new Jedis(hnp.getHost(), hnp.getPort()); j.connect(); j.auth("foobared"); j.flushAll(); @@ -31,7 +31,7 @@ public class PoolBenchmark { private static void withPool() throws Exception { final JedisPool pool = new JedisPool(new GenericObjectPoolConfig(), - hnp.host, hnp.port, 2000, "foobared"); + hnp.getHost(), hnp.getPort(), 2000, "foobared"); List tds = new ArrayList(); final AtomicInteger ind = new AtomicInteger(); @@ -59,5 +59,6 @@ public class PoolBenchmark { t.join(); pool.destroy(); + } } \ No newline at end of file diff --git a/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java index 6b523fd..c6d91c2 100644 --- a/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java +++ b/src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java @@ -3,8 +3,8 @@ package redis.clients.jedis.tests.commands; import org.junit.Test; import redis.clients.jedis.BinaryJedis; +import redis.clients.jedis.HostAndPort; import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; public class ConnectionHandlingCommandsTest extends JedisCommandTestBase { protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @@ -16,7 +16,7 @@ public class ConnectionHandlingCommandsTest extends JedisCommandTestBase { @Test public void binary_quit() { - BinaryJedis bj = new BinaryJedis(hnp.host); + BinaryJedis bj = new BinaryJedis(hnp.getHost()); assertEquals("OK", bj.quit()); } } \ No newline at end of file diff --git a/src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java b/src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java index 8d92c4c..bf787f9 100644 --- a/src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java +++ b/src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java @@ -1,18 +1,19 @@ package redis.clients.jedis.tests.commands; -import org.junit.After; -import org.junit.Before; -import org.junit.ComparisonFailure; -import redis.clients.jedis.Jedis; -import redis.clients.jedis.tests.HostAndPortUtil; -import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; -import redis.clients.jedis.tests.JedisTestBase; - import java.util.Arrays; import java.util.Iterator; import java.util.List; import java.util.Set; +import org.junit.After; +import org.junit.Before; +import org.junit.ComparisonFailure; + +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Jedis; +import redis.clients.jedis.tests.HostAndPortUtil; +import redis.clients.jedis.tests.JedisTestBase; + public abstract class JedisCommandTestBase extends JedisTestBase { protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); @@ -24,7 +25,7 @@ public abstract class JedisCommandTestBase extends JedisTestBase { @Before public void setUp() throws Exception { - jedis = new Jedis(hnp.host, hnp.port, 500); + jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500); jedis.connect(); jedis.auth("foobared"); jedis.configSet("timeout", "300"); @@ -37,7 +38,7 @@ public abstract class JedisCommandTestBase extends JedisTestBase { } protected Jedis createJedis() { - Jedis j = new Jedis(hnp.host, hnp.port); + Jedis j = new Jedis(hnp.getHost(), hnp.getPort()); j.connect(); j.auth("foobared"); j.flushAll(); diff --git a/src/test/java/redis/clients/jedis/tests/commands/PublishSubscribeCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/PublishSubscribeCommandsTest.java index c7a94f4..8f7ccaf 100644 --- a/src/test/java/redis/clients/jedis/tests/commands/PublishSubscribeCommandsTest.java +++ b/src/test/java/redis/clients/jedis/tests/commands/PublishSubscribeCommandsTest.java @@ -475,7 +475,7 @@ public class PublishSubscribeCommandsTest extends JedisCommandTestBase { @Test @Ignore public void subscribeWithoutConnecting() { try { - Jedis jedis = new Jedis(hnp.host, hnp.port); + Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort()); jedis.subscribe(new JedisPubSub() { public void onMessage(String channel, String message) { } diff --git a/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java b/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java index b3f6a7e..565c1a4 100644 --- a/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java +++ b/src/test/java/redis/clients/jedis/tests/commands/TransactionCommandsTest.java @@ -31,7 +31,7 @@ public class TransactionCommandsTest extends JedisCommandTestBase { public void setUp() throws Exception { super.setUp(); - nj = new Jedis(hnp.host, hnp.port, 500); + nj = new Jedis(hnp.getHost(), hnp.getPort(), 500); nj.connect(); nj.auth("foobared"); nj.flushAll(); diff --git a/src/test/java/redis/clients/jedis/tests/utils/JedisSentinelTestUtil.java b/src/test/java/redis/clients/jedis/tests/utils/JedisSentinelTestUtil.java new file mode 100644 index 0000000..cd8fdc6 --- /dev/null +++ b/src/test/java/redis/clients/jedis/tests/utils/JedisSentinelTestUtil.java @@ -0,0 +1,128 @@ +package redis.clients.jedis.tests.utils; + +import java.util.List; +import java.util.Map; + +import redis.clients.jedis.HostAndPort; +import redis.clients.jedis.Jedis; + +public class JedisSentinelTestUtil { + + public static void waitForSentinelRecognizeRedisReplication( + HostAndPort sentinel, String masterName, HostAndPort master, + List slaves) throws InterruptedException { + Jedis sentinelJedis = new Jedis(sentinel.getHost(), sentinel.getPort()); + while (true) { + Thread.sleep(1000); + + if (!isMasterRecognized(sentinelJedis, masterName, master)) { + System.out.println("Master not recognized by Sentinel " + + sentinel.getHost() + ":" + sentinel.getPort() + + ", sleep..."); + continue; + } + + if (!isSlavesRecognized(sentinelJedis, masterName, slaves)) { + System.out.println("Slaves not recognized by Sentinel " + + sentinel.getHost() + ":" + sentinel.getPort() + + ", sleep..."); + continue; + } + + // all recognized + break; + } + + } + + public static HostAndPort waitForNewPromotedMaster(HostAndPort sentinel, + String masterName, HostAndPort oldMaster) + throws InterruptedException { + Jedis sentinelJedis = new Jedis(sentinel.getHost(), sentinel.getPort()); + + HostAndPort newMaster = null; + while (true) { + Thread.sleep(1000); + + List sentinelMasterInfos = sentinelJedis + .sentinelGetMasterAddrByName(masterName); + if (sentinelMasterInfos == null) + continue; + + newMaster = new HostAndPort(sentinelMasterInfos.get(0), + Integer.parseInt(sentinelMasterInfos.get(1))); + + if (!newMaster.equals(oldMaster)) + break; + + System.out + .println("Sentinel's master is not yet changed, sleep..."); + } + + return newMaster; + } + + public static void waitForSentinelsRecognizeEachOthers() + throws InterruptedException { + // During failover, master has been changed + // It means that sentinels need to recognize other sentinels from new + // master's hello channel + // Without recognizing, Sentinels cannot run failover + + // Sentinels need to take some time to recognize each other... + // http://redis.io/topics/sentinel + // Sentinel Rule #8: Every Sentinel publishes a message to every + // monitored master + // Pub/Sub channel __sentinel__:hello, every five seconds, blabla... + + // FIXME There're no command for sentinel to list recognized sentinels + // so sleep wisely (channel's hello message interval + margin) + Thread.sleep(5000 + 500); + } + + private static boolean isMasterRecognized(Jedis sentinelJedis, + String masterName, HostAndPort master) { + List sentinelMasterInfos = sentinelJedis + .sentinelGetMasterAddrByName(masterName); + if (sentinelMasterInfos == null) + return false; + + HostAndPort sentinelMaster = new HostAndPort( + sentinelMasterInfos.get(0), + Integer.parseInt(sentinelMasterInfos.get(1))); + + return sentinelMaster.equals(master); + } + + private static boolean isSlavesRecognized(Jedis sentinelJedis, + String masterName, List slaves) { + List> slavesMap = sentinelJedis + .sentinelSlaves(masterName); + + if (slavesMap.size() != slaves.size()) + return false; + + int slavesRecognized = 0; + + for (HostAndPort slave : slaves) { + if (isSlaveFoundInSlavesMap(slavesMap, slave)) + slavesRecognized++; + } + + return slavesRecognized == slaves.size(); + } + + private static boolean isSlaveFoundInSlavesMap( + List> slavesMap, HostAndPort slave) { + for (Map slaveMap : slavesMap) { + HostAndPort sentinelSlave = new HostAndPort(slaveMap.get("ip"), + Integer.parseInt(slaveMap.get("port"))); + + if (sentinelSlave.equals(slave)) + return true; + } + + return false; + } + +}