From 1d29b759fe10b51dad245e0f46aa0b2518701fc0 Mon Sep 17 00:00:00 2001 From: Jungtaek Lim Date: Sun, 15 Jun 2014 21:50:38 +0900 Subject: [PATCH 1/2] Make it better to use URI from Jedis / JedisPool * no need to provide password / DB index when user uses URI * can provide timeout when user users URI --- .../java/redis/clients/jedis/BinaryJedis.java | 32 +++++--- src/main/java/redis/clients/jedis/Jedis.java | 80 ++++++++++--------- .../java/redis/clients/jedis/JedisPool.java | 33 +++++--- .../redis/clients/util/JedisURIHelper.java | 21 +++++ .../clients/jedis/tests/JedisPoolTest.java | 6 ++ .../redis/clients/jedis/tests/JedisTest.java | 18 ++++- 6 files changed, 134 insertions(+), 56 deletions(-) create mode 100644 src/main/java/redis/clients/util/JedisURIHelper.java diff --git a/src/main/java/redis/clients/jedis/BinaryJedis.java b/src/main/java/redis/clients/jedis/BinaryJedis.java index 781f17f..5f3d089 100644 --- a/src/main/java/redis/clients/jedis/BinaryJedis.java +++ b/src/main/java/redis/clients/jedis/BinaryJedis.java @@ -17,6 +17,7 @@ import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisException; import redis.clients.util.JedisByteHashMap; +import redis.clients.util.JedisURIHelper; import redis.clients.util.SafeEncoder; public class BinaryJedis implements BasicCommands, BinaryJedisCommands, @@ -27,11 +28,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, public BinaryJedis(final String host) { URI uri = URI.create(host); if (uri.getScheme() != null && uri.getScheme().equals("redis")) { - client = new Client(uri.getHost(), uri.getPort()); - client.auth(uri.getUserInfo().split(":", 2)[1]); - client.getStatusCodeReply(); - client.select(Integer.parseInt(uri.getPath().split("/", 2)[1])); - client.getStatusCodeReply(); + initializeClientFromURI(uri); } else { client = new Client(host); } @@ -53,11 +50,28 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, } public BinaryJedis(URI uri) { + initializeClientFromURI(uri); + } + + public BinaryJedis(final URI uri, final int timeout) { + initializeClientFromURI(uri); + client.setTimeout(timeout); + } + + private void initializeClientFromURI(URI uri) { client = new Client(uri.getHost(), uri.getPort()); - client.auth(uri.getUserInfo().split(":", 2)[1]); - client.getStatusCodeReply(); - client.select(Integer.parseInt(uri.getPath().split("/", 2)[1])); - client.getStatusCodeReply(); + + String password = JedisURIHelper.getPassword(uri); + if (password != null) { + client.auth(password); + client.getStatusCodeReply(); + } + + Integer dbIndex = JedisURIHelper.getDBIndex(uri); + if (dbIndex != null) { + client.select(dbIndex); + client.getStatusCodeReply(); + } } public String ping() { diff --git a/src/main/java/redis/clients/jedis/Jedis.java b/src/main/java/redis/clients/jedis/Jedis.java index fbf430c..cae04cd 100644 --- a/src/main/java/redis/clients/jedis/Jedis.java +++ b/src/main/java/redis/clients/jedis/Jedis.java @@ -35,6 +35,10 @@ public class Jedis extends BinaryJedis implements JedisCommands, super(uri); } + public Jedis(final URI uri, final int timeout) { + super(uri, timeout); + } + /** * Set the string value as value of the key. The string can't be longer than * 1073741824 bytes (1 GB). @@ -547,26 +551,27 @@ public class Jedis extends BinaryJedis implements JedisCommands, /** * INCRBYFLOAT *

- * INCRBYFLOAT commands are limited to double precision floating point values. + * INCRBYFLOAT commands are limited to double precision floating point + * values. *

* Note: this is actually a string operation, that is, in Redis there are * not "double" types. Simply the string stored at the key is parsed as a * base double precision floating point value, incremented, and then - * converted back as a string. There is no DECRYBYFLOAT but providing a + * converted back as a string. There is no DECRYBYFLOAT but providing a * negative value will work as expected. *

* Time complexity: O(1) - * + * * @param key * @param value * @return Double reply, this commands will reply with the new value of key * after the increment. */ public Double incrByFloat(final String key, final double value) { - checkIsInMulti(); - client.incrByFloat(key, value); - String dval = client.getBulkReply(); - return (dval != null ? new Double(dval) : null); + checkIsInMulti(); + client.incrByFloat(key, value); + String dval = client.getBulkReply(); + return (dval != null ? new Double(dval) : null); } /** @@ -763,28 +768,29 @@ public class Jedis extends BinaryJedis implements JedisCommands, /** * Increment the number stored at field in the hash at key by a double - * precision floating point value. If key does not exist, - * a new key holding a hash is created. If field does not - * exist or holds a string, the value is set to 0 before applying the - * operation. Since the value argument is signed you can use this command to - * perform both increments and decrements. + * precision floating point value. If key does not exist, a new key holding + * a hash is created. If field does not exist or holds a string, the value + * is set to 0 before applying the operation. Since the value argument is + * signed you can use this command to perform both increments and + * decrements. *

- * The range of values supported by HINCRBYFLOAT is limited to - * double precision floating point values. + * The range of values supported by HINCRBYFLOAT is limited to double + * precision floating point values. *

* Time complexity: O(1) - * + * * @param key * @param field * @param value - * @return Double precision floating point reply The new value at field after the increment - * operation. + * @return Double precision floating point reply The new value at field + * after the increment operation. */ - public Double hincrByFloat(final String key, final String field, final double value) { - checkIsInMulti(); - client.hincrByFloat(key, field, value); - final String dval = client.getBulkReply(); - return (dval != null ? new Double(dval) : null); + public Double hincrByFloat(final String key, final String field, + final double value) { + checkIsInMulti(); + client.hincrByFloat(key, field, value); + final String dval = client.getBulkReply(); + return (dval != null ? new Double(dval) : null); } /** @@ -2707,12 +2713,13 @@ public class Jedis extends BinaryJedis implements JedisCommands, client.getrange(key, startOffset, endOffset); return client.getBulkReply(); } - + public Long bitpos(final String key, final boolean value) { return bitpos(key, value, new BitPosParams()); } - - public Long bitpos(final String key, final boolean value, final BitPosParams params) { + + public Long bitpos(final String key, final boolean value, + final BitPosParams params) { client.bitpos(key, value, params); return client.getIntegerReply(); } @@ -3140,7 +3147,6 @@ public class Jedis extends BinaryJedis implements JedisCommands, return client.getIntegerReply(); } - public String psetex(final String key, final int milliseconds, final String value) { checkIsInMulti(); @@ -3435,55 +3441,55 @@ public class Jedis extends BinaryJedis implements JedisCommands, client.clusterSetSlotImporting(slot, nodeId); return client.getStatusCodeReply(); } - + public String clusterSetSlotStable(final int slot) { checkIsInMulti(); client.clusterSetSlotStable(slot); return client.getStatusCodeReply(); } - + public String clusterForget(final String nodeId) { checkIsInMulti(); client.clusterForget(nodeId); return client.getStatusCodeReply(); } - + public String clusterFlushSlots() { checkIsInMulti(); client.clusterFlushSlots(); return client.getStatusCodeReply(); } - + public Long clusterKeySlot(final String key) { checkIsInMulti(); client.clusterKeySlot(key); return client.getIntegerReply(); } - + public Long clusterCountKeysInSlot(final int slot) { checkIsInMulti(); client.clusterCountKeysInSlot(slot); return client.getIntegerReply(); } - + public String clusterSaveConfig() { checkIsInMulti(); client.clusterSaveConfig(); return client.getStatusCodeReply(); } - + public String clusterReplicate(final String nodeId) { checkIsInMulti(); client.clusterReplicate(nodeId); return client.getStatusCodeReply(); } - + public List clusterSlaves(final String nodeId) { checkIsInMulti(); client.clusterSlaves(nodeId); return client.getMultiBulkReply(); } - + public String clusterFailover() { checkIsInMulti(); client.clusterFailover(); @@ -3529,7 +3535,7 @@ public class Jedis extends BinaryJedis implements JedisCommands, } public void setDataSource(Pool jedisPool) { - this.dataSource = jedisPool; + this.dataSource = jedisPool; } public Long pfadd(final String key, final String... elements) { @@ -3546,7 +3552,7 @@ public class Jedis extends BinaryJedis implements JedisCommands, @Override public long pfcount(String... keys) { - checkIsInMulti(); + checkIsInMulti(); client.pfcount(keys); return client.getIntegerReply(); } diff --git a/src/main/java/redis/clients/jedis/JedisPool.java b/src/main/java/redis/clients/jedis/JedisPool.java index 0fbfdfe..763d15d 100644 --- a/src/main/java/redis/clients/jedis/JedisPool.java +++ b/src/main/java/redis/clients/jedis/JedisPool.java @@ -5,6 +5,7 @@ import java.net.URI; import org.apache.commons.pool2.impl.GenericObjectPool; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; +import redis.clients.util.JedisURIHelper; import redis.clients.util.Pool; public class JedisPool extends Pool { @@ -24,8 +25,12 @@ public class JedisPool extends Pool { if (uri.getScheme() != null && uri.getScheme().equals("redis")) { String h = uri.getHost(); int port = uri.getPort(); - String password = uri.getUserInfo().split(":", 2)[1]; - int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); + String password = JedisURIHelper.getPassword(uri); + int database = 0; + Integer dbIndex = JedisURIHelper.getDBIndex(uri); + if (dbIndex != null) { + database = dbIndex.intValue(); + } this.internalPool = new GenericObjectPool( new JedisFactory(h, port, Protocol.DEFAULT_TIMEOUT, password, database, null), @@ -39,13 +44,11 @@ public class JedisPool extends Pool { } public JedisPool(final URI uri) { - String h = uri.getHost(); - int port = uri.getPort(); - String password = uri.getUserInfo().split(":", 2)[1]; - int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); - this.internalPool = new GenericObjectPool(new JedisFactory(h, - port, Protocol.DEFAULT_TIMEOUT, password, database, null), - new GenericObjectPoolConfig()); + this(new GenericObjectPoolConfig(), uri, Protocol.DEFAULT_TIMEOUT); + } + + public JedisPool(final URI uri, final int timeout) { + this(new GenericObjectPoolConfig(), uri, timeout); } public JedisPool(final GenericObjectPoolConfig poolConfig, @@ -79,6 +82,18 @@ public class JedisPool extends Pool { database, clientName)); } + public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri) { + this(poolConfig, uri, Protocol.DEFAULT_TIMEOUT); + } + + public JedisPool(final GenericObjectPoolConfig poolConfig, final URI uri, + final int timeout) { + super(poolConfig, new JedisFactory(uri.getHost(), uri.getPort(), + timeout, JedisURIHelper.getPassword(uri), + JedisURIHelper.getDBIndex(uri) != null ? JedisURIHelper + .getDBIndex(uri) : 0, null)); + } + @Override public Jedis getResource() { Jedis jedis = super.getResource(); diff --git a/src/main/java/redis/clients/util/JedisURIHelper.java b/src/main/java/redis/clients/util/JedisURIHelper.java new file mode 100644 index 0000000..027fa3a --- /dev/null +++ b/src/main/java/redis/clients/util/JedisURIHelper.java @@ -0,0 +1,21 @@ +package redis.clients.util; + +import java.net.URI; + +public class JedisURIHelper { + public static String getPassword(URI uri) { + String userInfo = uri.getUserInfo(); + if (userInfo != null) { + return userInfo.split(":", 2)[1]; + } + return null; + } + + public static Integer getDBIndex(URI uri) { + String[] pathSplit = uri.getPath().split("/", 2); + if (pathSplit.length > 1) { + return Integer.parseInt(pathSplit[1]); + } + return null; + } +} diff --git a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java index 7d8e611..30aff37 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisPoolTest.java @@ -144,6 +144,12 @@ public class JedisPoolTest extends Assert { assertEquals("bar", jedis.get("foo")); } + @Test + public void allowUrlWithNoDBAndNoPassword() throws URISyntaxException { + new JedisPool("redis://localhost:6380"); + new JedisPool(new URI("redis://localhost:6380")); + } + @Test public void selectDatabaseOnActivation() { JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), diff --git a/src/test/java/redis/clients/jedis/tests/JedisTest.java b/src/test/java/redis/clients/jedis/tests/JedisTest.java index 3f5cdf1..abec911 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisTest.java @@ -57,6 +57,14 @@ public class JedisTest extends JedisCommandTestBase { jedis.hmget("foobar", "foo"); } + @Test(expected = JedisConnectionException.class) + public void timeoutConnectionWithURI() throws Exception { + jedis = new Jedis(new URI("redis://:foobared@localhost:6380/2"), 15000); + jedis.configSet("timeout", "1"); + Thread.sleep(2000); + jedis.hmget("foobar", "foo"); + } + @Test(expected = JedisDataException.class) public void failWhenSendingNullValues() { jedis.set("foo", null); @@ -92,7 +100,15 @@ public class JedisTest extends JedisCommandTestBase { assertEquals("PONG", jedis.ping()); assertEquals("bar", jedis.get("foo")); } - + + @Test + public void allowUrlWithNoDBAndNoPassword() { + Jedis jedis = new Jedis("redis://localhost:6380"); + assertEquals(jedis.getClient().getHost(), "localhost"); + assertEquals(jedis.getClient().getPort(), 6380); + assertEquals(jedis.getDB(), (Long) 0L); + } + @Test public void checkCloseable() { jedis.close(); From bfcecd73cb3b56a4f9ae99dac9bc068518f62224 Mon Sep 17 00:00:00 2001 From: Jungtaek Lim Date: Wed, 10 Sep 2014 20:46:57 +0900 Subject: [PATCH 2/2] JedisURIHelper.getDBIndex() now returns 0 when db index is not provided --- src/main/java/redis/clients/jedis/BinaryJedis.java | 2 +- src/main/java/redis/clients/util/JedisURIHelper.java | 9 +++++++-- src/test/java/redis/clients/jedis/tests/JedisTest.java | 7 +++++++ 3 files changed, 15 insertions(+), 3 deletions(-) diff --git a/src/main/java/redis/clients/jedis/BinaryJedis.java b/src/main/java/redis/clients/jedis/BinaryJedis.java index 5f3d089..b89fcc0 100644 --- a/src/main/java/redis/clients/jedis/BinaryJedis.java +++ b/src/main/java/redis/clients/jedis/BinaryJedis.java @@ -68,7 +68,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, } Integer dbIndex = JedisURIHelper.getDBIndex(uri); - if (dbIndex != null) { + if (dbIndex > 0) { client.select(dbIndex); client.getStatusCodeReply(); } diff --git a/src/main/java/redis/clients/util/JedisURIHelper.java b/src/main/java/redis/clients/util/JedisURIHelper.java index 027fa3a..d2039a8 100644 --- a/src/main/java/redis/clients/util/JedisURIHelper.java +++ b/src/main/java/redis/clients/util/JedisURIHelper.java @@ -14,8 +14,13 @@ public class JedisURIHelper { public static Integer getDBIndex(URI uri) { String[] pathSplit = uri.getPath().split("/", 2); if (pathSplit.length > 1) { - return Integer.parseInt(pathSplit[1]); + String dbIndexStr = pathSplit[1]; + if (dbIndexStr.isEmpty()) { + return 0; + } + return Integer.parseInt(dbIndexStr); + } else { + return 0; } - return null; } } diff --git a/src/test/java/redis/clients/jedis/tests/JedisTest.java b/src/test/java/redis/clients/jedis/tests/JedisTest.java index abec911..3b7a87f 100644 --- a/src/test/java/redis/clients/jedis/tests/JedisTest.java +++ b/src/test/java/redis/clients/jedis/tests/JedisTest.java @@ -104,6 +104,13 @@ public class JedisTest extends JedisCommandTestBase { @Test public void allowUrlWithNoDBAndNoPassword() { Jedis jedis = new Jedis("redis://localhost:6380"); + jedis.auth("foobared"); + assertEquals(jedis.getClient().getHost(), "localhost"); + assertEquals(jedis.getClient().getPort(), 6380); + assertEquals(jedis.getDB(), (Long) 0L); + + jedis = new Jedis("redis://localhost:6380/"); + jedis.auth("foobared"); assertEquals(jedis.getClient().getHost(), "localhost"); assertEquals(jedis.getClient().getPort(), 6380); assertEquals(jedis.getDB(), (Long) 0L);