diff --git a/Makefile b/Makefile
index 00f29bf..56f1910 100644
--- a/Makefile
+++ b/Makefile
@@ -3,6 +3,7 @@ daemonize yes
port 6379
requirepass foobared
pidfile /tmp/redis1.pid
+logfile /tmp/redis1.log
endef
define REDIS2_CONF
@@ -10,33 +11,86 @@ daemonize yes
port 6380
requirepass foobared
pidfile /tmp/redis2.pid
+logfile /tmp/redis2.log
endef
+define REDIS3_CONF
+daemonize yes
+port 6381
+pidfile /tmp/redis3.pid
+logfile /tmp/redis3.log
+endef
+
+define REDIS4_CONF
+daemonize yes
+port 6382
+pidfile /tmp/redis4.pid
+logfile /tmp/redis4.log
+endef
define REDIS_SENTINEL1
port 26379
daemonize yes
-sentinel monitor mymaster 127.0.0.1 6379 2
+sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster foobared
-sentinel down-after-milliseconds mymaster 5000
+sentinel down-after-milliseconds mymaster 1000
sentinel failover-timeout mymaster 900000
sentinel can-failover mymaster yes
sentinel parallel-syncs mymaster 1
pidfile /tmp/sentinel1.pid
+logfile /tmp/sentinel1.log
+endef
+
+define REDIS_SENTINEL2
+port 26380
+daemonize yes
+sentinel monitor mymaster 127.0.0.1 6381 2
+sentinel down-after-milliseconds mymaster 3000
+sentinel can-failover mymaster yes
+sentinel parallel-syncs mymaster 1
+sentinel failover-timeout mymaster 900000
+pidfile /tmp/sentinel2.pid
+logfile /tmp/sentinel2.log
+endef
+
+define REDIS_SENTINEL3
+port 26381
+daemonize yes
+sentinel monitor mymaster 127.0.0.1 6381 2
+sentinel down-after-milliseconds mymaster 3000
+sentinel can-failover mymaster yes
+sentinel parallel-syncs mymaster 1
+sentinel failover-timeout mymaster 900000
+pidfile /tmp/sentinel3.pid
+logfile /tmp/sentinel3.log
endef
export REDIS1_CONF
export REDIS2_CONF
+export REDIS3_CONF
+export REDIS4_CONF
export REDIS_SENTINEL1
+export REDIS_SENTINEL2
+export REDIS_SENTINEL3
+
test:
echo "$$REDIS1_CONF" | redis-server -
echo "$$REDIS2_CONF" | redis-server -
+ echo "$$REDIS3_CONF" | redis-server -
+ echo "$$REDIS4_CONF" | redis-server -
echo "$$REDIS_SENTINEL1" | redis-sentinel -
+ echo "$$REDIS_SENTINEL2" | redis-sentinel -
+ echo "$$REDIS_SENTINEL3" | redis-sentinel -
mvn clean compile test
kill `cat /tmp/redis1.pid`
kill `cat /tmp/redis2.pid`
+ # this get's segfaulted by the tests
+ kill `cat /tmp/redis3.pid` || true
+ kill `cat /tmp/redis4.pid`
kill `cat /tmp/sentinel1.pid`
+ kill `cat /tmp/sentinel2.pid`
+ kill `cat /tmp/sentinel3.pid`
.PHONY: test
diff --git a/pom.xml b/pom.xml
index a42dc27..a724a9d 100644
--- a/pom.xml
+++ b/pom.xml
@@ -13,7 +13,7 @@
2.2.2-SNAPSHOT
Jedis
Jedis is a blazingly small and sane Redis java client.
- https://github.com/mardambey/jedis
+ https://github.com/xetorthio/jedis
@@ -28,24 +28,25 @@
MIT
- http://github.com/mardambey/jedis/raw/master/LICENSE.txt
+ http://github.com/xetorthio/jedis/raw/master/LICENSE.txt
repo
github
- http://github.com/mardambey/jedis/issues
+ http://github.com/xetorthio/jedis/issues
- scm:git:git@github.com:mardambey/jedis.git
- scm:git:git@github.com:mardambey/jedis.git
- scm:git:git@github.com:mardambey/jedis.git
+ scm:git:git@github.com:xetorthio/jedis.git
+ scm:git:git@github.com:xetorthio/jedis.git
+ scm:git:git@github.com:xetorthio/jedis.git
- localhost:6379,localhost:6380
+ localhost:6379,localhost:6380,localhost:6381,localhost:6382
+ localhost:26379,localhost:26380
diff --git a/src/main/java/redis/clients/jedis/JedisSentinelPool.java b/src/main/java/redis/clients/jedis/JedisSentinelPool.java
index 9bee0e9..609c742 100644
--- a/src/main/java/redis/clients/jedis/JedisSentinelPool.java
+++ b/src/main/java/redis/clients/jedis/JedisSentinelPool.java
@@ -231,9 +231,13 @@ public class JedisSentinelPool extends Pool {
}, "+switch-master");
} catch (JedisConnectionException e) {
- log.severe("Lost connection to Sentinel at " + host + ":" + port + ". Sleeping 5000ms and retrying.");
- try { Thread.sleep(subscribeRetryWaitTimeMillis); } catch (InterruptedException e1) { e1.printStackTrace(); }
+ if (running.get()) {
+ log.severe("Lost connection to Sentinel at " + host + ":" + port + ". Sleeping 5000ms and retrying.");
+ try { Thread.sleep(subscribeRetryWaitTimeMillis); } catch (InterruptedException e1) { e1.printStackTrace(); }
+ } else {
+ log.fine("Unsubscribing from Sentinel at " + host + ":" + port);
+ }
}
}
}
diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java
index d167b84..db3d915 100644
--- a/src/main/java/redis/clients/jedis/Protocol.java
+++ b/src/main/java/redis/clients/jedis/Protocol.java
@@ -13,6 +13,7 @@ import redis.clients.util.SafeEncoder;
public final class Protocol {
public static final int DEFAULT_PORT = 6379;
+ public static final int DEFAULT_SENTINEL_PORT = 26379;
public static final int DEFAULT_TIMEOUT = 2000;
public static final int DEFAULT_DATABASE = 0;
diff --git a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
index 215cfc4..991cf35 100644
--- a/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
+++ b/src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java
@@ -6,56 +6,104 @@ import java.util.List;
import redis.clients.jedis.Protocol;
public class HostAndPortUtil {
- private static List hostAndPortList = new ArrayList(
- 2);
+ private static List redisHostAndPortList = new ArrayList();
+ private static List sentinelHostAndPortList = new ArrayList();
static {
- final HostAndPort defaulthnp1 = new HostAndPort();
+
+ HostAndPort defaulthnp1 = new HostAndPort();
defaulthnp1.host = "localhost";
- defaulthnp1.port = Protocol.DEFAULT_PORT;
- hostAndPortList.add(defaulthnp1);
+ defaulthnp1.port = Protocol.DEFAULT_PORT;
+ redisHostAndPortList.add(defaulthnp1);
- final HostAndPort defaulthnp2 = new HostAndPort();
+ HostAndPort defaulthnp2 = new HostAndPort();
defaulthnp2.host = "localhost";
defaulthnp2.port = Protocol.DEFAULT_PORT + 1;
- hostAndPortList.add(defaulthnp2);
+ redisHostAndPortList.add(defaulthnp2);
+
+ HostAndPort defaulthnp3 = new HostAndPort();
+ defaulthnp3.host = "localhost";
+ defaulthnp3.port = Protocol.DEFAULT_PORT + 2;
+ redisHostAndPortList.add(defaulthnp3);
+
+ HostAndPort defaulthnp4 = new HostAndPort();
+ defaulthnp4.host = "localhost";
+ defaulthnp4.port = Protocol.DEFAULT_PORT + 3;
+ redisHostAndPortList.add(defaulthnp4);
+
+ HostAndPort defaulthnp5 = new HostAndPort();
+ defaulthnp5.host = "localhost";
+ defaulthnp5.port = Protocol.DEFAULT_SENTINEL_PORT;
+ sentinelHostAndPortList.add(defaulthnp5);
+
+ HostAndPort defaulthnp6 = new HostAndPort();
+ defaulthnp6.host = "localhost";
+ defaulthnp6.port = Protocol.DEFAULT_SENTINEL_PORT + 1;
+ sentinelHostAndPortList.add(defaulthnp6);
+
+ HostAndPort defaulthnp7 = new HostAndPort();
+ defaulthnp7.host = "localhost";
+ defaulthnp7.port = Protocol.DEFAULT_SENTINEL_PORT + 2;
+ sentinelHostAndPortList.add(defaulthnp7);
- final String envHosts = System.getProperty("redis-hosts");
- if (null != envHosts && 0 < envHosts.length()) {
- final String[] hostDefs = envHosts.split(",");
+ String envRedisHosts = System.getProperty("redis-hosts");
+ String envSentinelHosts = System.getProperty("sentinel-hosts");
+
+ redisHostAndPortList = parseHosts(envRedisHosts, redisHostAndPortList);
+ sentinelHostAndPortList = parseHosts(envSentinelHosts, sentinelHostAndPortList);
+ }
+
+ public static List parseHosts(String envHosts, List existingHostsAndPorts) {
+
+ if (null != envHosts && 0 < envHosts.length()) {
+
+ String[] hostDefs = envHosts.split(",");
+
if (null != hostDefs && 2 <= hostDefs.length) {
- hostAndPortList = new ArrayList(
- hostDefs.length);
+
+ List envHostsAndPorts = new ArrayList(hostDefs.length);
+
for (String hostDef : hostDefs) {
- final String[] hostAndPort = hostDef.split(":");
+
+ String[] hostAndPort = hostDef.split(":");
+
if (null != hostAndPort && 2 == hostAndPort.length) {
- final HostAndPort hnp = new HostAndPort();
+
+ HostAndPort hnp = new HostAndPort();
hnp.host = hostAndPort[0];
+
try {
hnp.port = Integer.parseInt(hostAndPort[1]);
} catch (final NumberFormatException nfe) {
hnp.port = Protocol.DEFAULT_PORT;
- }
- hostAndPortList.add(hnp);
+ }
+
+ envHostsAndPorts.add(hnp);
}
}
+
+ return envHostsAndPorts;
}
}
- final StringBuilder strb = new StringBuilder(
- "Redis hosts to be used : ");
- for (HostAndPort hnp : hostAndPortList) {
- strb.append('[').append(hnp.host).append(':').append(hnp.port)
- .append(']').append(' ');
- }
- System.out.println(strb);
+
+ return existingHostsAndPorts;
}
-
+
public static List getRedisServers() {
- return hostAndPortList;
+ return redisHostAndPortList;
+ }
+
+ public static List getSentinelServers() {
+ 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/JedisSentinelPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java
new file mode 100644
index 0000000..5c8affe
--- /dev/null
+++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelPoolTest.java
@@ -0,0 +1,64 @@
+package redis.clients.jedis.tests;
+
+import java.util.HashSet;
+import java.util.Set;
+
+import org.junit.Before;
+import org.junit.Test;
+
+import redis.clients.jedis.DebugParams;
+import redis.clients.jedis.Jedis;
+import redis.clients.jedis.JedisSentinelPool;
+import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort;
+
+public class JedisSentinelPoolTest extends JedisTestBase {
+
+ protected static HostAndPort master = HostAndPortUtil.getRedisServers().get(2);
+ protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers().get(3);
+ protected static HostAndPort sentinel1 = HostAndPortUtil.getSentinelServers().get(1);
+ protected static HostAndPort sentinel2 = HostAndPortUtil.getSentinelServers().get(2);
+
+ protected static Jedis masterJedis;
+ protected static Jedis slaveJedis1;
+ protected static Jedis sentinelJedis1;
+
+ protected Set sentinels = new HashSet();
+
+ @Before
+ public void setUp() throws Exception {
+
+ // set up master and slaves
+ masterJedis = new Jedis(master.host, master.port);
+ masterJedis.slaveofNoOne();
+
+ slaveJedis1 = new Jedis(slave1.host, slave1.port);
+ slaveJedis1.slaveof(master.host, master.port);
+
+ sentinelJedis1 = new Jedis(sentinel1.host, sentinel1.port);
+ sentinels.add(sentinel1.toString());
+ sentinels.add(sentinel2.toString());
+
+ // FIXME: The following allows the master/slave relationship to
+ // be established. We can do this more elegantly.
+ Thread.sleep(10000);
+ }
+
+ @Test
+ public void segfaultMaster() throws InterruptedException {
+
+ JedisSentinelPool pool = new JedisSentinelPool("mymaster", sentinels);
+
+ Jedis jedis = pool.getResource();
+ assertEquals("PONG", jedis.ping());
+
+ try { masterJedis.debug(DebugParams.SEGFAULT()); } 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);
+
+ jedis = pool.getResource();
+ assertEquals("PONG", jedis.ping());
+ }
+}
diff --git a/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java b/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java
index 5d5d48d..a3dc68a 100644
--- a/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java
+++ b/src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java
@@ -49,7 +49,7 @@ public class JedisSentinelTest {
assertEquals("6379", masterHostAndPort.get(1));
List