Merging with upstream, necessary changes, shifting poolConfig as private instance variable from JedisClusterConnectionHandler to JedisClusterInfoCache due to design change in previous commits.
This commit is contained in:
16
Makefile
16
Makefile
@@ -116,6 +116,18 @@ pidfile /tmp/sentinel3.pid
|
||||
logfile /tmp/sentinel3.log
|
||||
endef
|
||||
|
||||
define REDIS_SENTINEL4
|
||||
port 26382
|
||||
daemonize yes
|
||||
sentinel monitor mymaster 127.0.0.1 6381 1
|
||||
sentinel auth-pass mymaster foobared
|
||||
sentinel down-after-milliseconds mymaster 2000
|
||||
sentinel parallel-syncs mymaster 1
|
||||
sentinel failover-timeout mymaster 120000
|
||||
pidfile /tmp/sentinel4.pid
|
||||
logfile /tmp/sentinel4.log
|
||||
endef
|
||||
|
||||
# CLUSTER REDIS NODES
|
||||
define REDIS_CLUSTER_NODE1_CONF
|
||||
daemonize yes
|
||||
@@ -199,6 +211,7 @@ export REDIS7_CONF
|
||||
export REDIS_SENTINEL1
|
||||
export REDIS_SENTINEL2
|
||||
export REDIS_SENTINEL3
|
||||
export REDIS_SENTINEL4
|
||||
export REDIS_CLUSTER_NODE1_CONF
|
||||
export REDIS_CLUSTER_NODE2_CONF
|
||||
export REDIS_CLUSTER_NODE3_CONF
|
||||
@@ -219,6 +232,8 @@ start: cleanup
|
||||
echo "$$REDIS_SENTINEL2" > /tmp/sentinel2.conf && redis-server /tmp/sentinel2.conf --sentinel
|
||||
@sleep 0.5
|
||||
echo "$$REDIS_SENTINEL3" > /tmp/sentinel3.conf && redis-server /tmp/sentinel3.conf --sentinel
|
||||
@sleep 0.5
|
||||
echo "$$REDIS_SENTINEL4" > /tmp/sentinel4.conf && redis-server /tmp/sentinel4.conf --sentinel
|
||||
echo "$$REDIS_CLUSTER_NODE1_CONF" | redis-server -
|
||||
echo "$$REDIS_CLUSTER_NODE2_CONF" | redis-server -
|
||||
echo "$$REDIS_CLUSTER_NODE3_CONF" | redis-server -
|
||||
@@ -241,6 +256,7 @@ stop:
|
||||
kill `cat /tmp/sentinel1.pid`
|
||||
kill `cat /tmp/sentinel2.pid`
|
||||
kill `cat /tmp/sentinel3.pid`
|
||||
kill `cat /tmp/sentinel4.pid`
|
||||
kill `cat /tmp/redis_cluster_node1.pid` || true
|
||||
kill `cat /tmp/redis_cluster_node2.pid` || true
|
||||
kill `cat /tmp/redis_cluster_node3.pid` || true
|
||||
|
||||
@@ -3,7 +3,7 @@ apply plugin: 'maven'
|
||||
apply plugin: 'eclipse'
|
||||
|
||||
group = 'com.googlecode.jedis'
|
||||
archiveBaseName = 'jedis'
|
||||
archivesBaseName = 'jedis'
|
||||
version = '1.5.0'
|
||||
|
||||
repositories {
|
||||
|
||||
2
pom.xml
2
pom.xml
@@ -9,7 +9,7 @@
|
||||
<packaging>jar</packaging>
|
||||
<groupId>redis.clients</groupId>
|
||||
<artifactId>jedis</artifactId>
|
||||
<version>2.5.2-SNAPSHOT</version>
|
||||
<version>2.5.3-SNAPSHOT</version>
|
||||
<name>Jedis</name>
|
||||
<description>Jedis is a blazingly small and sane Redis java client.</description>
|
||||
<url>https://github.com/xetorthio/jedis</url>
|
||||
|
||||
@@ -7,6 +7,7 @@ import redis.clients.util.SafeEncoder;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import static redis.clients.jedis.Protocol.Command.*;
|
||||
@@ -827,6 +828,25 @@ public class BinaryClient extends Connection {
|
||||
args.addAll(params.getParams());
|
||||
sendCommand(ZINTERSTORE, args.toArray(new byte[args.size()][]));
|
||||
}
|
||||
|
||||
public void zlexcount(final byte[] key, final byte[] min, final byte[] max) {
|
||||
sendCommand(ZLEXCOUNT, key, min, max);
|
||||
}
|
||||
|
||||
public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
sendCommand(ZRANGEBYLEX, key, min, max);
|
||||
}
|
||||
|
||||
public void zrangeByLex(final byte[] key, final byte[] min, final byte[] max,
|
||||
final int offset, final int count) {
|
||||
sendCommand(ZRANGEBYLEX, key, min, max, LIMIT.raw,
|
||||
toByteArray(offset), toByteArray(count));
|
||||
}
|
||||
|
||||
public void zremrangeByLex(byte[] key, byte[] min, byte[] max) {
|
||||
sendCommand(ZREMRANGEBYLEX, key, min, max);
|
||||
}
|
||||
|
||||
|
||||
public void save() {
|
||||
sendCommand(SAVE);
|
||||
@@ -963,9 +983,6 @@ public class BinaryClient extends Connection {
|
||||
}
|
||||
|
||||
public void resetState() {
|
||||
if (isInMulti())
|
||||
discard();
|
||||
|
||||
if (isInWatch())
|
||||
unwatch();
|
||||
}
|
||||
@@ -1099,11 +1116,6 @@ public class BinaryClient extends Connection {
|
||||
sendCommand(RESTORE, key, toByteArray(ttl), serializedValue);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pexpire(final byte[] key, final int milliseconds) {
|
||||
pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
public void pexpire(final byte[] key, final long milliseconds) {
|
||||
sendCommand(PEXPIRE, key, toByteArray(milliseconds));
|
||||
}
|
||||
@@ -1165,61 +1177,6 @@ public class BinaryClient extends Connection {
|
||||
sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void scan(int cursor, final ScanParams params) {
|
||||
final List<byte[]> args = new ArrayList<byte[]>();
|
||||
args.add(toByteArray(cursor));
|
||||
args.addAll(params.getParams());
|
||||
sendCommand(SCAN, args.toArray(new byte[args.size()][]));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void hscan(final byte[] key, int cursor, final ScanParams params) {
|
||||
final List<byte[]> args = new ArrayList<byte[]>();
|
||||
args.add(key);
|
||||
args.add(toByteArray(cursor));
|
||||
args.addAll(params.getParams());
|
||||
sendCommand(HSCAN, args.toArray(new byte[args.size()][]));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void sscan(final byte[] key, int cursor, final ScanParams params) {
|
||||
final List<byte[]> args = new ArrayList<byte[]>();
|
||||
args.add(key);
|
||||
args.add(toByteArray(cursor));
|
||||
args.addAll(params.getParams());
|
||||
sendCommand(SSCAN, args.toArray(new byte[args.size()][]));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void zscan(final byte[] key, int cursor, final ScanParams params) {
|
||||
final List<byte[]> args = new ArrayList<byte[]>();
|
||||
args.add(key);
|
||||
args.add(toByteArray(cursor));
|
||||
args.addAll(params.getParams());
|
||||
sendCommand(ZSCAN, args.toArray(new byte[args.size()][]));
|
||||
}
|
||||
|
||||
public void scan(final byte[] cursor, final ScanParams params) {
|
||||
final List<byte[]> args = new ArrayList<byte[]>();
|
||||
args.add(cursor);
|
||||
|
||||
@@ -17,21 +17,20 @@ 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,
|
||||
MultiKeyBinaryCommands, AdvancedBinaryJedisCommands,
|
||||
BinaryScriptingCommands, Closeable {
|
||||
protected Client client = null;
|
||||
|
||||
protected Transaction transaction = null;
|
||||
protected Pipeline pipeline = null;
|
||||
|
||||
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 +52,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 > 0) {
|
||||
client.select(dbIndex);
|
||||
client.getStatusCodeReply();
|
||||
}
|
||||
}
|
||||
|
||||
public String ping() {
|
||||
@@ -1753,7 +1769,9 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
|
||||
public Transaction multi() {
|
||||
client.multi();
|
||||
return new Transaction(client);
|
||||
client.getOne(); // expected OK
|
||||
transaction = new Transaction(client);
|
||||
return transaction;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
@@ -1767,6 +1785,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
List<Object> results = null;
|
||||
jedisTransaction.setClient(client);
|
||||
client.multi();
|
||||
client.getOne(); // expected OK
|
||||
jedisTransaction.execute();
|
||||
results = jedisTransaction.exec();
|
||||
return results;
|
||||
@@ -1789,9 +1808,23 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
|
||||
public void resetState() {
|
||||
if (client.isConnected()) {
|
||||
if (transaction != null) {
|
||||
transaction.clear();
|
||||
}
|
||||
|
||||
if (pipeline != null) {
|
||||
pipeline.clear();
|
||||
}
|
||||
|
||||
if (client.isInWatch()) {
|
||||
unwatch();
|
||||
}
|
||||
|
||||
client.resetState();
|
||||
client.getAll();
|
||||
}
|
||||
|
||||
transaction = null;
|
||||
pipeline = null;
|
||||
}
|
||||
|
||||
public String watch(final byte[]... keys) {
|
||||
@@ -2207,7 +2240,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
}
|
||||
|
||||
public Pipeline pipelined() {
|
||||
Pipeline pipeline = new Pipeline();
|
||||
pipeline = new Pipeline();
|
||||
pipeline.setClient(client);
|
||||
return pipeline;
|
||||
}
|
||||
@@ -2793,6 +2826,35 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {
|
||||
checkIsInMulti();
|
||||
client.zlexcount(key, min, max);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
checkIsInMulti();
|
||||
client.zrangeByLex(key, min, max);
|
||||
return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,
|
||||
final int offset, final int count) {
|
||||
checkIsInMulti();
|
||||
client.zrangeByLex(key, min, max, offset, count);
|
||||
return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
checkIsInMulti();
|
||||
client.zremrangeByLex(key, min, max);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
/**
|
||||
* Synchronously save the DB on disk.
|
||||
* <p>
|
||||
@@ -3385,11 +3447,6 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Long pexpire(final byte[] key, final int milliseconds) {
|
||||
return pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
public Long pexpire(final byte[] key, final long milliseconds) {
|
||||
checkIsInMulti();
|
||||
client.pexpire(key, milliseconds);
|
||||
|
||||
@@ -115,6 +115,8 @@ public interface BinaryJedisCommands {
|
||||
|
||||
byte[] srandmember(byte[] key);
|
||||
|
||||
List<byte[]> srandmember(final byte[] key, final int count);
|
||||
|
||||
Long strlen(byte[] key);
|
||||
|
||||
Long zadd(byte[] key, double score, byte[] member);
|
||||
@@ -194,6 +196,15 @@ public interface BinaryJedisCommands {
|
||||
Long zremrangeByScore(byte[] key, double start, double end);
|
||||
|
||||
Long zremrangeByScore(byte[] key, byte[] start, byte[] end);
|
||||
|
||||
Long zlexcount(final byte[] key, final byte[] min, final byte[] max);
|
||||
|
||||
Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max);
|
||||
|
||||
Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,
|
||||
int offset, int count);
|
||||
|
||||
Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max);
|
||||
|
||||
Long linsert(byte[] key, Client.LIST_POSITION where, byte[] pivot,
|
||||
byte[] value);
|
||||
|
||||
@@ -34,7 +34,7 @@ public interface BinaryRedisPipeline {
|
||||
|
||||
Response<byte[]> getSet(byte[] key, byte[] value);
|
||||
|
||||
Response<Long> getrange(byte[] key, long startOffset, long endOffset);
|
||||
Response<byte[]> getrange(byte[] key, long startOffset, long endOffset);
|
||||
|
||||
Response<Long> hdel(byte[] key, byte[]... field);
|
||||
|
||||
@@ -206,6 +206,15 @@ public interface BinaryRedisPipeline {
|
||||
Response<Long> zrevrank(byte[] key, byte[] member);
|
||||
|
||||
Response<Double> zscore(byte[] key, byte[] member);
|
||||
|
||||
Response<Long> zlexcount(final byte[] key, final byte[] min, final byte[] max);
|
||||
|
||||
Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] max, final byte[] min);
|
||||
|
||||
Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] max, final byte[] min,
|
||||
int offset, int count);
|
||||
|
||||
Response<Long> zremrangeByLex(final byte[] key, final byte[] min, final byte[] max);
|
||||
|
||||
Response<Long> bitcount(byte[] key);
|
||||
|
||||
|
||||
@@ -300,6 +300,12 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
|
||||
return j.srandmember(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List srandmember(byte[] key, int count) {
|
||||
Jedis j = getShard(key);
|
||||
return j.srandmember(key, count);
|
||||
}
|
||||
|
||||
public Long zadd(byte[] key, double score, byte[] member) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zadd(key, score, member);
|
||||
@@ -484,6 +490,31 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
|
||||
Jedis j = getShard(key);
|
||||
return j.zremrangeByScore(key, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zlexcount(final byte[] key, final byte[] min, final byte[] max) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zlexcount(key, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zrangeByLex(key, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<byte[]> zrangeByLex(final byte[] key, final byte[] min, final byte[] max,
|
||||
final int offset, final int count) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zrangeByLex(key, min, max, offset, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zremrangeByLex(key, min, max);
|
||||
}
|
||||
|
||||
public Long linsert(byte[] key, LIST_POSITION where, byte[] pivot,
|
||||
byte[] value) {
|
||||
|
||||
@@ -9,6 +9,7 @@ import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import redis.clients.util.JedisByteHashMap;
|
||||
import redis.clients.util.SafeEncoder;
|
||||
|
||||
public class BuilderFactory {
|
||||
@@ -104,6 +105,26 @@ public class BuilderFactory {
|
||||
|
||||
};
|
||||
|
||||
public static final Builder<Map<String, String>> PUBSUB_NUMSUB_MAP = new Builder<Map<String, String>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<String, String> build(Object data) {
|
||||
final List<Object> flatHash = (List<Object>) data;
|
||||
final Map<String, String> hash = new HashMap<String, String>();
|
||||
final Iterator<Object> iterator = flatHash.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
hash.put(SafeEncoder.encode((byte[]) iterator.next()),
|
||||
String.valueOf((Long) iterator.next()));
|
||||
}
|
||||
|
||||
return hash;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "PUBSUB_NUMSUB_MAP<String, String>";
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
public static final Builder<Set<String>> STRING_SET = new Builder<Set<String>>() {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Set<String> build(Object data) {
|
||||
@@ -170,7 +191,7 @@ public class BuilderFactory {
|
||||
@SuppressWarnings("unchecked")
|
||||
public Map<byte[], byte[]> build(Object data) {
|
||||
final List<byte[]> flatHash = (List<byte[]>) data;
|
||||
final Map<byte[], byte[]> hash = new HashMap<byte[], byte[]>();
|
||||
final Map<byte[], byte[]> hash = new JedisByteHashMap();
|
||||
final Iterator<byte[]> iterator = flatHash.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
hash.put(iterator.next(), iterator.next());
|
||||
|
||||
@@ -585,6 +585,24 @@ public class Client extends BinaryClient implements Commands {
|
||||
}
|
||||
zinterstore(SafeEncoder.encode(dstkey), params, bsets);
|
||||
}
|
||||
|
||||
public void zlexcount(final String key, final String min, final String max) {
|
||||
zlexcount(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));
|
||||
}
|
||||
|
||||
public void zrangeByLex(final String key, final String min, final String max) {
|
||||
zrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));
|
||||
}
|
||||
|
||||
public void zrangeByLex(final String key, final String min, final String max,
|
||||
final int offset, final int count) {
|
||||
zrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max),
|
||||
offset, count);
|
||||
}
|
||||
|
||||
public void zremrangeByLex(final String key, final String min, final String max) {
|
||||
zremrangeByLex(SafeEncoder.encode(key), SafeEncoder.encode(min), SafeEncoder.encode(max));
|
||||
}
|
||||
|
||||
public void strlen(final String key) {
|
||||
strlen(SafeEncoder.encode(key));
|
||||
@@ -780,11 +798,6 @@ public class Client extends BinaryClient implements Commands {
|
||||
restore(SafeEncoder.encode(key), ttl, serializedValue);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public void pexpire(final String key, final int milliseconds) {
|
||||
pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
public void pexpire(final String key, final long milliseconds) {
|
||||
pexpire(SafeEncoder.encode(key), milliseconds);
|
||||
}
|
||||
@@ -841,36 +854,6 @@ public class Client extends BinaryClient implements Commands {
|
||||
increment);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void hscan(final String key, int cursor, final ScanParams params) {
|
||||
hscan(SafeEncoder.encode(key), cursor, params);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void sscan(final String key, int cursor, final ScanParams params) {
|
||||
sscan(SafeEncoder.encode(key), cursor, params);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void zscan(final String key, int cursor, final ScanParams params) {
|
||||
zscan(SafeEncoder.encode(key), cursor, params);
|
||||
}
|
||||
|
||||
public void scan(final String cursor, final ScanParams params) {
|
||||
scan(SafeEncoder.encode(cursor), params);
|
||||
}
|
||||
@@ -1011,4 +994,8 @@ public void clusterSetSlotStable(final int slot) {
|
||||
public void clusterFailover() {
|
||||
cluster(Protocol.CLUSTER_FAILOVER);
|
||||
}
|
||||
|
||||
public void clusterSlots() {
|
||||
cluster(Protocol.CLUSTER_SLOTS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,4 +38,6 @@ public interface ClusterCommands {
|
||||
List<String> clusterSlaves(final String nodeId);
|
||||
|
||||
String clusterFailover();
|
||||
|
||||
List<Object> clusterSlots();
|
||||
}
|
||||
|
||||
@@ -301,38 +301,6 @@ public interface Commands {
|
||||
|
||||
public void bitop(BitOP op, final String destKey, String... srcKeys);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void scan(int cursor, final ScanParams params);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void hscan(final String key, int cursor, final ScanParams params);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void sscan(final String key, int cursor, final ScanParams params);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public void zscan(final String key, int cursor, final ScanParams params);
|
||||
|
||||
public void scan(final String cursor, final ScanParams params);
|
||||
|
||||
public void hscan(final String key, final String cursor, final ScanParams params);
|
||||
|
||||
@@ -21,7 +21,6 @@ public class Connection implements Closeable {
|
||||
private Socket socket;
|
||||
private RedisOutputStream outputStream;
|
||||
private RedisInputStream inputStream;
|
||||
private int pipelinedCommands = 0;
|
||||
private int timeout = Protocol.DEFAULT_TIMEOUT;
|
||||
|
||||
private boolean broken = false;
|
||||
@@ -78,7 +77,6 @@ public class Connection implements Closeable {
|
||||
try {
|
||||
connect();
|
||||
Protocol.sendCommand(outputStream, cmd, args);
|
||||
pipelinedCommands++;
|
||||
return this;
|
||||
} catch (JedisConnectionException ex) {
|
||||
// Any other exceptions related to connection?
|
||||
@@ -91,7 +89,6 @@ public class Connection implements Closeable {
|
||||
try {
|
||||
connect();
|
||||
Protocol.sendCommand(outputStream, cmd, new byte[0][]);
|
||||
pipelinedCommands++;
|
||||
return this;
|
||||
} catch (JedisConnectionException ex) {
|
||||
// Any other exceptions related to connection?
|
||||
@@ -180,7 +177,6 @@ public class Connection implements Closeable {
|
||||
|
||||
protected String getStatusCodeReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
final byte[] resp = (byte[]) readProtocolWithCheckingBroken();
|
||||
if (null == resp) {
|
||||
return null;
|
||||
@@ -200,13 +196,11 @@ public class Connection implements Closeable {
|
||||
|
||||
public byte[] getBinaryBulkReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return (byte[]) readProtocolWithCheckingBroken();
|
||||
}
|
||||
|
||||
public Long getIntegerReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return (Long) readProtocolWithCheckingBroken();
|
||||
}
|
||||
|
||||
@@ -217,14 +211,9 @@ public class Connection implements Closeable {
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<byte[]> getBinaryMultiBulkReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return (List<byte[]>) readProtocolWithCheckingBroken();
|
||||
}
|
||||
|
||||
public void resetPipelinedCount() {
|
||||
pipelinedCommands = 0;
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Object> getRawObjectMultiBulkReply() {
|
||||
return (List<Object>) readProtocolWithCheckingBroken();
|
||||
@@ -232,38 +221,17 @@ public class Connection implements Closeable {
|
||||
|
||||
public List<Object> getObjectMultiBulkReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return getRawObjectMultiBulkReply();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public List<Long> getIntegerMultiBulkReply() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return (List<Long>) readProtocolWithCheckingBroken();
|
||||
}
|
||||
|
||||
public List<Object> getAll() {
|
||||
return getAll(0);
|
||||
}
|
||||
|
||||
public List<Object> getAll(int except) {
|
||||
List<Object> all = new ArrayList<Object>();
|
||||
flush();
|
||||
while (pipelinedCommands > except) {
|
||||
try {
|
||||
all.add(readProtocolWithCheckingBroken());
|
||||
} catch (JedisDataException e) {
|
||||
all.add(e);
|
||||
}
|
||||
pipelinedCommands--;
|
||||
}
|
||||
return all;
|
||||
flush();
|
||||
return (List<Long>) Protocol.read(inputStream);
|
||||
}
|
||||
|
||||
public Object getOne() {
|
||||
flush();
|
||||
pipelinedCommands--;
|
||||
return readProtocolWithCheckingBroken();
|
||||
}
|
||||
|
||||
@@ -288,4 +256,17 @@ public class Connection implements Closeable {
|
||||
throw exc;
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> getMany(int count) {
|
||||
flush();
|
||||
List<Object> responses = new ArrayList<Object>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
try {
|
||||
responses.add(readProtocolWithCheckingBroken());
|
||||
} catch (JedisDataException e) {
|
||||
responses.add(e);
|
||||
}
|
||||
}
|
||||
return responses;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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
|
||||
* <p>
|
||||
* INCRBYFLOAT commands are limited to double precision floating point values.
|
||||
* INCRBYFLOAT commands are limited to double precision floating point
|
||||
* values.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* 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.
|
||||
* <p>
|
||||
* <b>Time complexity:</b> 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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1116,8 +1122,8 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
|
||||
/**
|
||||
* Atomically return and remove the first (LPOP) or last (RPOP) element of
|
||||
* the list. For example if the list contains the elements "a","b","c" LPOP
|
||||
* will return "a" and the list will become "b","c".
|
||||
* the list. For example if the list contains the elements "a","b","c" RPOP
|
||||
* will return "c" and the list will become "a","b".
|
||||
* <p>
|
||||
* If the key does not exist or the list is already empty the special value
|
||||
* 'nil' is returned.
|
||||
@@ -2609,6 +2615,35 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
client.zinterstore(dstkey, params, sets);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zlexcount(final String key, final String min, final String max) {
|
||||
checkIsInMulti();
|
||||
client.zlexcount(key, min, max);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max) {
|
||||
checkIsInMulti();
|
||||
client.zrangeByLex(key, min, max);
|
||||
return new LinkedHashSet<String>(client.getMultiBulkReply());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max,
|
||||
final int offset, final int count) {
|
||||
checkIsInMulti();
|
||||
client.zrangeByLex(key, min, max, offset, count);
|
||||
return new LinkedHashSet<String>(client.getMultiBulkReply());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zremrangeByLex(final String key, final String min, final String max) {
|
||||
checkIsInMulti();
|
||||
client.zremrangeByLex(key, min, max);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
public Long strlen(final String key) {
|
||||
client.strlen(key);
|
||||
@@ -2707,12 +2742,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();
|
||||
}
|
||||
@@ -3117,11 +3153,6 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Long pexpire(final String key, final int milliseconds) {
|
||||
return pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
public Long pexpire(final String key, final long milliseconds) {
|
||||
checkIsInMulti();
|
||||
client.pexpire(key, milliseconds);
|
||||
@@ -3140,7 +3171,6 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
|
||||
|
||||
public String psetex(final String key, final int milliseconds,
|
||||
final String value) {
|
||||
checkIsInMulti();
|
||||
@@ -3180,131 +3210,6 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<String> scan(int cursor) {
|
||||
return scan(cursor, new ScanParams());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<String> scan(int cursor, final ScanParams params) {
|
||||
checkIsInMulti();
|
||||
client.scan(cursor, params);
|
||||
List<Object> result = client.getObjectMultiBulkReply();
|
||||
int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
|
||||
List<String> results = new ArrayList<String>();
|
||||
List<byte[]> rawResults = (List<byte[]>) result.get(1);
|
||||
for (byte[] bs : rawResults) {
|
||||
results.add(SafeEncoder.encode(bs));
|
||||
}
|
||||
return new ScanResult<String>(newcursor, results);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Map.Entry<String, String>> hscan(final String key,
|
||||
int cursor) {
|
||||
return hscan(key, cursor, new ScanParams());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Map.Entry<String, String>> hscan(final String key,
|
||||
int cursor, final ScanParams params) {
|
||||
checkIsInMulti();
|
||||
client.hscan(key, cursor, params);
|
||||
List<Object> result = client.getObjectMultiBulkReply();
|
||||
int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
|
||||
List<Map.Entry<String, String>> results = new ArrayList<Map.Entry<String, String>>();
|
||||
List<byte[]> rawResults = (List<byte[]>) result.get(1);
|
||||
Iterator<byte[]> iterator = rawResults.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
results.add(new AbstractMap.SimpleEntry<String, String>(SafeEncoder
|
||||
.encode(iterator.next()), SafeEncoder.encode(iterator
|
||||
.next())));
|
||||
}
|
||||
return new ScanResult<Map.Entry<String, String>>(newcursor, results);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<String> sscan(final String key, int cursor) {
|
||||
return sscan(key, cursor, new ScanParams());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<String> sscan(final String key, int cursor,
|
||||
final ScanParams params) {
|
||||
checkIsInMulti();
|
||||
client.sscan(key, cursor, params);
|
||||
List<Object> result = client.getObjectMultiBulkReply();
|
||||
int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
|
||||
List<String> results = new ArrayList<String>();
|
||||
List<byte[]> rawResults = (List<byte[]>) result.get(1);
|
||||
for (byte[] bs : rawResults) {
|
||||
results.add(SafeEncoder.encode(bs));
|
||||
}
|
||||
return new ScanResult<String>(newcursor, results);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Tuple> zscan(final String key, int cursor) {
|
||||
return zscan(key, cursor, new ScanParams());
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Tuple> zscan(final String key, int cursor,
|
||||
final ScanParams params) {
|
||||
checkIsInMulti();
|
||||
client.zscan(key, cursor, params);
|
||||
List<Object> result = client.getObjectMultiBulkReply();
|
||||
int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
|
||||
List<Tuple> results = new ArrayList<Tuple>();
|
||||
List<byte[]> rawResults = (List<byte[]>) result.get(1);
|
||||
Iterator<byte[]> iterator = rawResults.iterator();
|
||||
while (iterator.hasNext()) {
|
||||
results.add(new Tuple(SafeEncoder.encode(iterator.next()), Double
|
||||
.valueOf(SafeEncoder.encode(iterator.next()))));
|
||||
}
|
||||
return new ScanResult<Tuple>(newcursor, results);
|
||||
}
|
||||
|
||||
public ScanResult<String> scan(final String cursor) {
|
||||
return scan(cursor, new ScanParams());
|
||||
}
|
||||
@@ -3435,60 +3340,67 @@ 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<String> clusterSlaves(final String nodeId) {
|
||||
checkIsInMulti();
|
||||
client.clusterSlaves(nodeId);
|
||||
return client.getMultiBulkReply();
|
||||
}
|
||||
|
||||
|
||||
public String clusterFailover() {
|
||||
checkIsInMulti();
|
||||
client.clusterFailover();
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Object> clusterSlots() {
|
||||
checkIsInMulti();
|
||||
client.clusterSlots();
|
||||
return client.getObjectMultiBulkReply();
|
||||
}
|
||||
|
||||
public String asking() {
|
||||
checkIsInMulti();
|
||||
@@ -3511,7 +3423,7 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
public Map<String, String> pubsubNumSub(String... channels) {
|
||||
checkIsInMulti();
|
||||
client.pubsubNumSub(channels);
|
||||
return BuilderFactory.STRING_MAP
|
||||
return BuilderFactory.PUBSUB_NUMSUB_MAP
|
||||
.build(client.getBinaryMultiBulkReply());
|
||||
}
|
||||
|
||||
@@ -3529,7 +3441,7 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
}
|
||||
|
||||
public void setDataSource(Pool<Jedis> jedisPool) {
|
||||
this.dataSource = jedisPool;
|
||||
this.dataSource = jedisPool;
|
||||
}
|
||||
|
||||
public Long pfadd(final String key, final String... elements) {
|
||||
@@ -3546,7 +3458,7 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
|
||||
@Override
|
||||
public long pfcount(String... keys) {
|
||||
checkIsInMulti();
|
||||
checkIsInMulti();
|
||||
client.pfcount(keys);
|
||||
return client.getIntegerReply();
|
||||
}
|
||||
@@ -3556,4 +3468,31 @@ public class Jedis extends BinaryJedis implements JedisCommands,
|
||||
client.pfmerge(destkey, sourcekeys);
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> blpop(int timeout, String key) {
|
||||
checkIsInMulti();
|
||||
List<String> args = new ArrayList<String>();
|
||||
args.add(key);
|
||||
args.add(String.valueOf(timeout));
|
||||
client.blpop(args.toArray(new String[args.size()]));
|
||||
client.setTimeoutInfinite();
|
||||
final List<String> multiBulkReply = client.getMultiBulkReply();
|
||||
client.rollbackTimeout();
|
||||
return multiBulkReply;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> brpop(int timeout, String key) {
|
||||
checkIsInMulti();
|
||||
List<String> args = new ArrayList<String>();
|
||||
args.add(key);
|
||||
args.add(String.valueOf(timeout));
|
||||
client.brpop(args.toArray(new String[args.size()]));
|
||||
client.setTimeoutInfinite();
|
||||
final List<String> multiBulkReply = client.getMultiBulkReply();
|
||||
client.rollbackTimeout();
|
||||
return multiBulkReply;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package redis.clients.jedis;
|
||||
|
||||
import redis.clients.jedis.BinaryClient.LIST_POSITION;
|
||||
|
||||
import java.io.Closeable;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
@@ -9,7 +10,7 @@ import java.util.Set;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
|
||||
public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
public class JedisCluster implements JedisCommands, BasicCommands, Closeable {
|
||||
public static final short HASHSLOTS = 16384;
|
||||
private static final int DEFAULT_TIMEOUT = 1;
|
||||
private static final int DEFAULT_MAX_REDIRECTIONS = 5;
|
||||
@@ -50,6 +51,21 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
this.timeout = timeout;
|
||||
this.maxRedirections = maxRedirections;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
if (connectionHandler != null) {
|
||||
for (JedisPool pool : connectionHandler.getNodes().values()) {
|
||||
try {
|
||||
if (pool != null) {
|
||||
pool.destroy();
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// pass
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String set(final String key, final String value) {
|
||||
@@ -412,7 +428,7 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public Long execute(Jedis connection) {
|
||||
return connection.hdel(key);
|
||||
return connection.hlen(key);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
@@ -641,6 +657,17 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> srandmember(final String key, final int count) {
|
||||
return new JedisClusterCommand<List<String>>(connectionHandler, timeout,
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public List<String> execute(Jedis connection) {
|
||||
return connection.srandmember(key, count);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long strlen(final String key) {
|
||||
return new JedisClusterCommand<Long>(connectionHandler, timeout,
|
||||
@@ -1093,6 +1120,51 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zlexcount(final String key, final String min, final String max) {
|
||||
return new JedisClusterCommand<Long>(connectionHandler, timeout,
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public Long execute(Jedis connection) {
|
||||
return connection.zlexcount(key, min, max);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max) {
|
||||
return new JedisClusterCommand<Set<String>>(connectionHandler, timeout,
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public Set<String> execute(Jedis connection) {
|
||||
return connection.zrangeByLex(key, min, max);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max,
|
||||
final int offset, final int count) {
|
||||
return new JedisClusterCommand<Set<String>>(connectionHandler, timeout,
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public Set<String> execute(Jedis connection) {
|
||||
return connection.zrangeByLex(key, min, max, offset, count);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zremrangeByLex(final String key, final String min, final String max) {
|
||||
return new JedisClusterCommand<Long>(connectionHandler, timeout,
|
||||
maxRedirections) {
|
||||
@Override
|
||||
public Long execute(Jedis connection) {
|
||||
return connection.zremrangeByLex(key, min, max);
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long linsert(final String key, final LIST_POSITION where,
|
||||
@@ -1426,58 +1498,6 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
@Override
|
||||
public ScanResult<Entry<String, String>> hscan(final String key,
|
||||
final int cursor) {
|
||||
return new JedisClusterCommand<ScanResult<Entry<String, String>>>(
|
||||
connectionHandler, timeout, maxRedirections) {
|
||||
@Override
|
||||
public ScanResult<Entry<String, String>> execute(Jedis connection) {
|
||||
return connection.hscan(key, cursor);
|
||||
}
|
||||
}.run(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
@Override
|
||||
public ScanResult<String> sscan(final String key, final int cursor) {
|
||||
return new JedisClusterCommand<ScanResult<String>>(connectionHandler,
|
||||
timeout, maxRedirections) {
|
||||
@Override
|
||||
public ScanResult<String> execute(Jedis connection) {
|
||||
return connection.sscan(key, cursor);
|
||||
}
|
||||
}.run(null);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
@Override
|
||||
public ScanResult<Tuple> zscan(final String key, final int cursor) {
|
||||
return new JedisClusterCommand<ScanResult<Tuple>>(connectionHandler,
|
||||
timeout, maxRedirections) {
|
||||
@Override
|
||||
public ScanResult<Tuple> execute(Jedis connection) {
|
||||
return connection.zscan(key, cursor);
|
||||
}
|
||||
}.run(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ScanResult<Entry<String, String>> hscan(final String key,
|
||||
final String cursor) {
|
||||
@@ -1533,4 +1553,26 @@ public class JedisCluster implements JedisCommands, BasicCommands {
|
||||
}
|
||||
}.run(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> blpop(final int timeout, final String key) {
|
||||
return new JedisClusterCommand<List<String>>(connectionHandler,
|
||||
timeout, maxRedirections) {
|
||||
@Override
|
||||
public List<String> execute(Jedis connection) {
|
||||
return connection.blpop(timeout,key);
|
||||
}
|
||||
}.run(null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> brpop(final int timeout, final String key) {
|
||||
return new JedisClusterCommand<List<String>>(connectionHandler,
|
||||
timeout, maxRedirections) {
|
||||
@Override
|
||||
public List<String> execute(Jedis connection) {
|
||||
return connection.brpop(timeout,key);
|
||||
}
|
||||
}.run(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -63,33 +63,35 @@ public abstract class JedisClusterCommand<T> {
|
||||
// maybe all connection is down
|
||||
throw jce;
|
||||
}
|
||||
|
||||
|
||||
releaseConnection(connection, true);
|
||||
connection = null;
|
||||
|
||||
|
||||
// retry with random connection
|
||||
return runWithRetries(key, redirections--, true, asking);
|
||||
} catch (JedisRedirectionException jre) {
|
||||
if (jre instanceof JedisAskDataException) {
|
||||
asking = true;
|
||||
this.connectionHandler.assignSlotToNode(jre.getSlot(),
|
||||
jre.getTargetNode());
|
||||
} else if (jre instanceof JedisMovedDataException) {
|
||||
// TODO : In antirez's redis-rb-cluster implementation,
|
||||
// it rebuilds cluster's slot and node cache
|
||||
// it rebuilds cluster's slot cache
|
||||
// recommended by Redis cluster specification
|
||||
this.connectionHandler.renewSlotCache();
|
||||
} else {
|
||||
throw new JedisClusterException(jre);
|
||||
}
|
||||
|
||||
this.connectionHandler.assignSlotToNode(jre.getSlot(),
|
||||
jre.getTargetNode());
|
||||
|
||||
releaseConnection(connection, false);
|
||||
connection = null;
|
||||
|
||||
|
||||
return runWithRetries(key, redirections - 1, false, asking);
|
||||
} finally {
|
||||
releaseConnection(connection, false);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
private void releaseConnection(Jedis connection, boolean broken) {
|
||||
if (connection != null) {
|
||||
if (broken) {
|
||||
|
||||
@@ -1,131 +1,86 @@
|
||||
package redis.clients.jedis;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
import redis.clients.util.ClusterNodeInformation;
|
||||
import redis.clients.util.ClusterNodeInformationParser;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Random;
|
||||
import java.util.Set;
|
||||
|
||||
import static redis.clients.jedis.JedisClusterInfoCache.getNodeKey;
|
||||
|
||||
public abstract class JedisClusterConnectionHandler {
|
||||
public static ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();
|
||||
|
||||
protected Map<String, JedisPool> nodes = new HashMap<String, JedisPool>();
|
||||
protected Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>();
|
||||
final protected GenericObjectPoolConfig poolConfig;
|
||||
protected final JedisClusterInfoCache cache;
|
||||
|
||||
abstract Jedis getConnection();
|
||||
|
||||
protected void returnConnection(Jedis connection) {
|
||||
nodes.get(getNodeKey(connection.getClient()))
|
||||
.returnResource(connection);
|
||||
public void returnConnection(Jedis connection) {
|
||||
cache.getNode(getNodeKey(connection.getClient())).returnResource(
|
||||
connection);
|
||||
}
|
||||
|
||||
public void returnBrokenConnection(Jedis connection) {
|
||||
nodes.get(getNodeKey(connection.getClient())).returnBrokenResource(
|
||||
cache.getNode(getNodeKey(connection.getClient())).returnBrokenResource(
|
||||
connection);
|
||||
}
|
||||
|
||||
abstract Jedis getConnectionFromSlot(int slot);
|
||||
|
||||
public JedisClusterConnectionHandler(Set<HostAndPort> nodes, final GenericObjectPoolConfig poolConfig) {
|
||||
this.poolConfig = poolConfig;
|
||||
initializeSlotsCache(nodes);
|
||||
this.cache = new JedisClusterInfoCache(poolConfig);
|
||||
initializeSlotsCache(nodes, poolConfig);
|
||||
}
|
||||
|
||||
public Map<String, JedisPool> getNodes() {
|
||||
return nodes;
|
||||
return cache.getNodes();
|
||||
}
|
||||
|
||||
private void initializeSlotsCache(Set<HostAndPort> startNodes) {
|
||||
public void assignSlotToNode(int slot, HostAndPort targetNode) {
|
||||
cache.assignSlotToNode(slot, targetNode);
|
||||
}
|
||||
|
||||
private void initializeSlotsCache(Set<HostAndPort> startNodes, GenericObjectPoolConfig poolConfig) {
|
||||
for (HostAndPort hostAndPort : startNodes) {
|
||||
JedisPool jp = new JedisPool(poolConfig, hostAndPort.getHost(),
|
||||
hostAndPort.getPort());
|
||||
|
||||
this.nodes.clear();
|
||||
this.slots.clear();
|
||||
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
jedis = jp.getResource();
|
||||
discoverClusterNodesAndSlots(jedis);
|
||||
cache.discoverClusterNodesAndSlots(jedis);
|
||||
break;
|
||||
} catch (JedisConnectionException e) {
|
||||
if (jedis != null) {
|
||||
jp.returnBrokenResource(jedis);
|
||||
jedis = null;
|
||||
}
|
||||
|
||||
// try next nodes
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jp.returnResource(jedis);
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (HostAndPort node : startNodes) {
|
||||
setNodeIfNotExist(node);
|
||||
cache.setNodeIfNotExist(node);
|
||||
}
|
||||
}
|
||||
|
||||
private void discoverClusterNodesAndSlots(Jedis jedis) {
|
||||
String localNodes = jedis.clusterNodes();
|
||||
for (String nodeInfo : localNodes.split("\n")) {
|
||||
ClusterNodeInformation clusterNodeInfo = nodeInfoParser.parse(
|
||||
nodeInfo, new HostAndPort(jedis.getClient().getHost(),
|
||||
jedis.getClient().getPort()));
|
||||
|
||||
HostAndPort targetNode = clusterNodeInfo.getNode();
|
||||
setNodeIfNotExist(targetNode);
|
||||
assignSlotsToNode(clusterNodeInfo.getAvailableSlots(), targetNode);
|
||||
}
|
||||
}
|
||||
|
||||
public void assignSlotToNode(int slot, HostAndPort targetNode) {
|
||||
JedisPool targetPool = nodes.get(getNodeKey(targetNode));
|
||||
|
||||
if (targetPool == null) {
|
||||
setNodeIfNotExist(targetNode);
|
||||
targetPool = nodes.get(getNodeKey(targetNode));
|
||||
}
|
||||
slots.put(slot, targetPool);
|
||||
}
|
||||
|
||||
public void assignSlotsToNode(List<Integer> targetSlots,
|
||||
HostAndPort targetNode) {
|
||||
JedisPool targetPool = nodes.get(getNodeKey(targetNode));
|
||||
|
||||
if (targetPool == null) {
|
||||
setNodeIfNotExist(targetNode);
|
||||
targetPool = nodes.get(getNodeKey(targetNode));
|
||||
}
|
||||
|
||||
for (Integer slot : targetSlots) {
|
||||
slots.put(slot, targetPool);
|
||||
public void renewSlotCache() {
|
||||
for (JedisPool jp : cache.getNodes().values()) {
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
jedis = jp.getResource();
|
||||
cache.discoverClusterSlots(jedis);
|
||||
break;
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected JedisPool getRandomConnection() {
|
||||
Object[] nodeArray = nodes.values().toArray();
|
||||
Object[] nodeArray = cache.getNodes().values().toArray();
|
||||
return (JedisPool) (nodeArray[new Random().nextInt(nodeArray.length)]);
|
||||
}
|
||||
|
||||
protected String getNodeKey(HostAndPort hnp) {
|
||||
return hnp.getHost() + ":" + hnp.getPort();
|
||||
}
|
||||
|
||||
protected String getNodeKey(Client client) {
|
||||
return client.getHost() + ":" + client.getPort();
|
||||
}
|
||||
|
||||
private void setNodeIfNotExist(HostAndPort node) {
|
||||
String nodeKey = getNodeKey(node);
|
||||
if (nodes.containsKey(nodeKey))
|
||||
return;
|
||||
|
||||
JedisPool nodePool = new JedisPool(poolConfig, node.getHost(), node.getPort());
|
||||
nodes.put(nodeKey, nodePool);
|
||||
}
|
||||
}
|
||||
|
||||
188
src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
Normal file
188
src/main/java/redis/clients/jedis/JedisClusterInfoCache.java
Normal file
@@ -0,0 +1,188 @@
|
||||
package redis.clients.jedis;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import redis.clients.util.ClusterNodeInformation;
|
||||
import redis.clients.util.ClusterNodeInformationParser;
|
||||
import redis.clients.util.SafeEncoder;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantReadWriteLock;
|
||||
|
||||
public class JedisClusterInfoCache {
|
||||
public static final ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();
|
||||
|
||||
private Map<String, JedisPool> nodes = new HashMap<String, JedisPool>();
|
||||
private Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>();
|
||||
|
||||
private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
|
||||
private final Lock r = rwl.readLock();
|
||||
private final Lock w = rwl.writeLock();
|
||||
private final GenericObjectPoolConfig poolConfig;
|
||||
|
||||
public JedisClusterInfoCache(final GenericObjectPoolConfig poolConfig) {
|
||||
this.poolConfig = poolConfig;
|
||||
}
|
||||
|
||||
public void discoverClusterNodesAndSlots(Jedis jedis) {
|
||||
w.lock();
|
||||
|
||||
try {
|
||||
this.nodes.clear();
|
||||
this.slots.clear();
|
||||
|
||||
String localNodes = jedis.clusterNodes();
|
||||
for (String nodeInfo : localNodes.split("\n")) {
|
||||
ClusterNodeInformation clusterNodeInfo = nodeInfoParser.parse(
|
||||
nodeInfo, new HostAndPort(jedis.getClient().getHost(),
|
||||
jedis.getClient().getPort()));
|
||||
|
||||
HostAndPort targetNode = clusterNodeInfo.getNode();
|
||||
setNodeIfNotExist(targetNode);
|
||||
assignSlotsToNode(clusterNodeInfo.getAvailableSlots(),
|
||||
targetNode);
|
||||
}
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void discoverClusterSlots(Jedis jedis) {
|
||||
w.lock();
|
||||
|
||||
try {
|
||||
this.slots.clear();
|
||||
|
||||
List<Object> slots = jedis.clusterSlots();
|
||||
|
||||
for (Object slotInfoObj : slots) {
|
||||
List<Object> slotInfo = (List<Object>) slotInfoObj;
|
||||
|
||||
if (slotInfo.size() <= 2) {
|
||||
continue;
|
||||
}
|
||||
|
||||
List<Integer> slotNums = getAssignedSlotArray(slotInfo);
|
||||
|
||||
// hostInfos
|
||||
List<Object> hostInfos = (List<Object>) slotInfo.get(2);
|
||||
if (hostInfos.size() <= 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
// at this time, we just use master, discard slave information
|
||||
HostAndPort targetNode = generateHostAndPort(hostInfos);
|
||||
|
||||
setNodeIfNotExist(targetNode);
|
||||
assignSlotsToNode(slotNums, targetNode);
|
||||
}
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
private HostAndPort generateHostAndPort(List<Object> hostInfos) {
|
||||
return new HostAndPort(SafeEncoder.encode((byte[]) hostInfos.get(0)),
|
||||
((Long) hostInfos.get(1)).intValue());
|
||||
}
|
||||
|
||||
public void setNodeIfNotExist(HostAndPort node) {
|
||||
w.lock();
|
||||
try {
|
||||
String nodeKey = getNodeKey(node);
|
||||
if (nodes.containsKey(nodeKey))
|
||||
return;
|
||||
|
||||
JedisPool nodePool = new JedisPool(poolConfig, node.getHost(), node.getPort());
|
||||
nodes.put(nodeKey, nodePool);
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public void assignSlotToNode(int slot, HostAndPort targetNode) {
|
||||
w.lock();
|
||||
try {
|
||||
JedisPool targetPool = nodes.get(getNodeKey(targetNode));
|
||||
|
||||
if (targetPool == null) {
|
||||
setNodeIfNotExist(targetNode);
|
||||
targetPool = nodes.get(getNodeKey(targetNode));
|
||||
}
|
||||
slots.put(slot, targetPool);
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void assignSlotsToNode(List<Integer> targetSlots,
|
||||
HostAndPort targetNode) {
|
||||
w.lock();
|
||||
try {
|
||||
JedisPool targetPool = nodes.get(getNodeKey(targetNode));
|
||||
|
||||
if (targetPool == null) {
|
||||
setNodeIfNotExist(targetNode);
|
||||
targetPool = nodes.get(getNodeKey(targetNode));
|
||||
}
|
||||
|
||||
for (Integer slot : targetSlots) {
|
||||
slots.put(slot, targetPool);
|
||||
}
|
||||
} finally {
|
||||
w.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized JedisPool getNode(String nodeKey) {
|
||||
r.lock();
|
||||
try {
|
||||
return nodes.get(nodeKey);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized JedisPool getSlotPool(int slot) {
|
||||
r.lock();
|
||||
try {
|
||||
return slots.get(slot);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized Map<String, JedisPool> getNodes() {
|
||||
r.lock();
|
||||
try {
|
||||
return new HashMap<String, JedisPool>(nodes);
|
||||
} finally {
|
||||
r.unlock();
|
||||
}
|
||||
}
|
||||
|
||||
public static String getNodeKey(HostAndPort hnp) {
|
||||
return hnp.getHost() + ":" + hnp.getPort();
|
||||
}
|
||||
|
||||
public static String getNodeKey(Client client) {
|
||||
return client.getHost() + ":" + client.getPort();
|
||||
}
|
||||
|
||||
public static String getNodeKey(Jedis jedis) {
|
||||
return getNodeKey(jedis.getClient());
|
||||
}
|
||||
|
||||
private List<Integer> getAssignedSlotArray(List<Object> slotInfo) {
|
||||
List<Integer> slotNums = new ArrayList<Integer>();
|
||||
for (int slot = ((Long) slotInfo.get(0)).intValue(); slot <= ((Long) slotInfo
|
||||
.get(1)).intValue(); slot++) {
|
||||
slotNums.add(slot);
|
||||
}
|
||||
return slotNums;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -113,6 +113,8 @@ public interface JedisCommands {
|
||||
|
||||
String srandmember(String key);
|
||||
|
||||
List<String> srandmember(String key, int count);
|
||||
|
||||
Long strlen(String key);
|
||||
|
||||
Long zadd(String key, double score, String member);
|
||||
@@ -192,6 +194,15 @@ public interface JedisCommands {
|
||||
Long zremrangeByScore(String key, double start, double end);
|
||||
|
||||
Long zremrangeByScore(String key, String start, String end);
|
||||
|
||||
Long zlexcount(final String key, final String min, final String max);
|
||||
|
||||
Set<String> zrangeByLex(final String key, final String min, final String max);
|
||||
|
||||
Set<String> zrangeByLex(final String key, final String min, final String max,
|
||||
final int offset, final int count);
|
||||
|
||||
Long zremrangeByLex(final String key, final String min, final String max);
|
||||
|
||||
Long linsert(String key, Client.LIST_POSITION where, String pivot,
|
||||
String value);
|
||||
@@ -201,8 +212,12 @@ public interface JedisCommands {
|
||||
Long rpushx(String key, String... string);
|
||||
|
||||
List<String> blpop(String arg);
|
||||
|
||||
List<String> blpop(int timeout, String key);
|
||||
|
||||
List<String> brpop(String arg);
|
||||
|
||||
List<String> brpop(int timeout, String key);
|
||||
|
||||
Long del(String key);
|
||||
|
||||
@@ -214,30 +229,6 @@ public interface JedisCommands {
|
||||
|
||||
Long bitcount(final String key, long start, long end);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
ScanResult<Map.Entry<String, String>> hscan(final String key, int cursor);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
ScanResult<String> sscan(final String key, int cursor);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
ScanResult<Tuple> zscan(final String key, int cursor);
|
||||
|
||||
ScanResult<Map.Entry<String, String>> hscan(final String key, final String cursor);
|
||||
|
||||
ScanResult<String> sscan(final String key, final String cursor);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
package redis.clients.jedis;
|
||||
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import org.apache.commons.pool2.PooledObject;
|
||||
import org.apache.commons.pool2.PooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
@@ -8,8 +10,7 @@ import org.apache.commons.pool2.impl.DefaultPooledObject;
|
||||
* PoolableObjectFactory custom impl.
|
||||
*/
|
||||
class JedisFactory implements PooledObjectFactory<Jedis> {
|
||||
private final String host;
|
||||
private final int port;
|
||||
private final AtomicReference<HostAndPort> hostAndPort = new AtomicReference<HostAndPort>();
|
||||
private final int timeout;
|
||||
private final String password;
|
||||
private final int database;
|
||||
@@ -23,14 +24,17 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
|
||||
public JedisFactory(final String host, final int port, final int timeout,
|
||||
final String password, final int database, final String clientName) {
|
||||
super();
|
||||
this.host = host;
|
||||
this.port = port;
|
||||
this.hostAndPort.set(new HostAndPort(host, port));
|
||||
this.timeout = timeout;
|
||||
this.password = password;
|
||||
this.database = database;
|
||||
this.clientName = clientName;
|
||||
}
|
||||
|
||||
public void setHostAndPort(final HostAndPort hostAndPort) {
|
||||
this.hostAndPort.set(hostAndPort);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void activateObject(PooledObject<Jedis> pooledJedis)
|
||||
throws Exception {
|
||||
@@ -60,7 +64,8 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
|
||||
|
||||
@Override
|
||||
public PooledObject<Jedis> makeObject() throws Exception {
|
||||
final Jedis jedis = new Jedis(this.host, this.port, this.timeout);
|
||||
final HostAndPort hostAndPort = this.hostAndPort.get();
|
||||
final Jedis jedis = new Jedis(hostAndPort.getHost(), hostAndPort.getPort(), this.timeout);
|
||||
|
||||
jedis.connect();
|
||||
if (null != this.password) {
|
||||
@@ -86,7 +91,13 @@ class JedisFactory implements PooledObjectFactory<Jedis> {
|
||||
public boolean validateObject(PooledObject<Jedis> pooledJedis) {
|
||||
final BinaryJedis jedis = pooledJedis.getObject();
|
||||
try {
|
||||
return jedis.isConnected() && jedis.ping().equals("PONG");
|
||||
HostAndPort hostAndPort = this.hostAndPort.get();
|
||||
|
||||
String connectionHost = jedis.getClient().getHost();
|
||||
int connectionPort = jedis.getClient().getPort();
|
||||
|
||||
return hostAndPort.getHost().equals(connectionHost) && hostAndPort.getPort() == connectionPort &&
|
||||
jedis.isConnected() && jedis.ping().equals("PONG");
|
||||
} catch (final Exception e) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -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<Jedis> {
|
||||
@@ -24,8 +25,12 @@ public class JedisPool extends Pool<Jedis> {
|
||||
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<Jedis>(
|
||||
new JedisFactory(h, port, Protocol.DEFAULT_TIMEOUT,
|
||||
password, database, null),
|
||||
@@ -39,13 +44,11 @@ public class JedisPool extends Pool<Jedis> {
|
||||
}
|
||||
|
||||
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<Jedis>(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<Jedis> {
|
||||
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();
|
||||
@@ -98,4 +113,12 @@ public class JedisPool extends Pool<Jedis> {
|
||||
returnResourceObject(resource);
|
||||
}
|
||||
}
|
||||
|
||||
public int getNumActive() {
|
||||
if (this.internalPool == null || this.internalPool.isClosed()) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return this.internalPool.getNumActive();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -162,12 +162,6 @@ public abstract class JedisPubSub {
|
||||
|
||||
/* Invalidate instance since this thread is no longer listening */
|
||||
this.client = null;
|
||||
|
||||
/*
|
||||
* Reset pipeline count because subscribe() calls would have increased
|
||||
* it but nothing decremented it.
|
||||
*/
|
||||
client.resetPipelinedCount();
|
||||
}
|
||||
|
||||
public int getSubscribedChannels() {
|
||||
|
||||
@@ -65,6 +65,7 @@ public class JedisSentinelPool extends Pool<Jedis> {
|
||||
public JedisSentinelPool(String masterName, Set<String> sentinels,
|
||||
final GenericObjectPoolConfig poolConfig, int timeout,
|
||||
final String password, final int database) {
|
||||
|
||||
this.poolConfig = poolConfig;
|
||||
this.timeout = timeout;
|
||||
this.password = password;
|
||||
@@ -74,6 +75,7 @@ public class JedisSentinelPool extends Pool<Jedis> {
|
||||
initPool(master);
|
||||
}
|
||||
|
||||
private volatile JedisFactory factory;
|
||||
private volatile HostAndPort currentHostMaster;
|
||||
|
||||
public void destroy() {
|
||||
@@ -91,10 +93,18 @@ public class JedisSentinelPool extends Pool<Jedis> {
|
||||
private void initPool(HostAndPort master) {
|
||||
if (!master.equals(currentHostMaster)) {
|
||||
currentHostMaster = master;
|
||||
if (factory == null) {
|
||||
factory = new JedisFactory(master.getHost(), master.getPort(),
|
||||
timeout, password, database);
|
||||
initPool(poolConfig, factory);
|
||||
} else {
|
||||
factory.setHostAndPort(currentHostMaster);
|
||||
// although we clear the pool, we still have to check the returned object
|
||||
// in getResource, this call only clears idle instances, not borrowed instances
|
||||
internalPool.clear();
|
||||
}
|
||||
|
||||
log.info("Created JedisPool to master at " + master);
|
||||
initPool(poolConfig,
|
||||
new JedisFactory(master.getHost(), master.getPort(),
|
||||
timeout, password, database));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -115,19 +125,30 @@ public class JedisSentinelPool extends Pool<Jedis> {
|
||||
|
||||
log.fine("Connecting to Sentinel " + hap);
|
||||
|
||||
Jedis jedis = null;
|
||||
try {
|
||||
Jedis jedis = new Jedis(hap.getHost(), hap.getPort());
|
||||
jedis = new Jedis(hap.getHost(), hap.getPort());
|
||||
|
||||
if (master == null) {
|
||||
master = toHostAndPort(jedis
|
||||
.sentinelGetMasterAddrByName(masterName));
|
||||
List<String> masterAddr = jedis
|
||||
.sentinelGetMasterAddrByName(masterName);
|
||||
if (masterAddr == null || masterAddr.size() != 2) {
|
||||
log.warning("Can not get master addr, master name: "
|
||||
+ masterName + ". Sentinel: " + hap + ".");
|
||||
continue;
|
||||
}
|
||||
|
||||
master = toHostAndPort(masterAddr);
|
||||
log.fine("Found Redis master at " + master);
|
||||
jedis.disconnect();
|
||||
break outer;
|
||||
}
|
||||
} catch (JedisConnectionException e) {
|
||||
log.warning("Cannot connect to sentinel running @ " + hap
|
||||
+ ". Trying next one.");
|
||||
} finally {
|
||||
if (jedis != null) {
|
||||
jedis.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,9 +185,22 @@ public class JedisSentinelPool extends Pool<Jedis> {
|
||||
|
||||
@Override
|
||||
public Jedis getResource() {
|
||||
Jedis jedis = super.getResource();
|
||||
jedis.setDataSource(this);
|
||||
return jedis;
|
||||
while (true) {
|
||||
Jedis jedis = super.getResource();
|
||||
jedis.setDataSource(this);
|
||||
|
||||
// get a reference because it can change concurrently
|
||||
final HostAndPort master = currentHostMaster;
|
||||
final HostAndPort connection = new HostAndPort(jedis.getClient().getHost(),
|
||||
jedis.getClient().getPort());
|
||||
|
||||
if (master.equals(connection)) {
|
||||
// connected to the correct master
|
||||
return jedis;
|
||||
} else {
|
||||
returnBrokenResource(jedis);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void returnBrokenResource(final Jedis resource) {
|
||||
|
||||
@@ -48,14 +48,9 @@ public class JedisSlotBasedConnectionHandler extends
|
||||
throw new JedisConnectionException("no reachable node in cluster");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void assignSlotToNode(int slot, HostAndPort targetNode) {
|
||||
super.assignSlotToNode(slot, targetNode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Jedis getConnectionFromSlot(int slot) {
|
||||
JedisPool connectionPool = slots.get(slot);
|
||||
JedisPool connectionPool = cache.getSlotPool(slot);
|
||||
if (connectionPool != null) {
|
||||
// It can't guaranteed to get valid connection because of node assignment
|
||||
return connectionPool.getResource();
|
||||
@@ -66,7 +61,7 @@ public class JedisSlotBasedConnectionHandler extends
|
||||
|
||||
private List<JedisPool> getShuffledNodesPool() {
|
||||
List<JedisPool> pools = new ArrayList<JedisPool>();
|
||||
pools.addAll(nodes.values());
|
||||
pools.addAll(cache.getNodes().values());
|
||||
Collections.shuffle(pools);
|
||||
return pools;
|
||||
}
|
||||
|
||||
@@ -70,14 +70,6 @@ public interface MultiKeyCommands {
|
||||
|
||||
Long bitop(BitOP op, final String destKey, String... srcKeys);
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
ScanResult<String> scan(int cursor);
|
||||
|
||||
ScanResult<String> scan(final String cursor);
|
||||
|
||||
String pfmerge(final String destkey, final String... sourcekeys);
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
package redis.clients.jedis;
|
||||
|
||||
import redis.clients.jedis.exceptions.JedisDataException;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import redis.clients.jedis.exceptions.JedisDataException;
|
||||
|
||||
public class Pipeline extends MultiKeyPipelineBase {
|
||||
|
||||
private MultiResponseBuilder currentMulti;
|
||||
@@ -26,7 +26,13 @@ public class Pipeline extends MultiKeyPipelineBase {
|
||||
for (int i = 0; i < list.size(); i++) {
|
||||
Response<?> response = responses.get(i);
|
||||
response.set(list.get(i));
|
||||
values.add(response.get());
|
||||
Object builtResponse;
|
||||
try {
|
||||
builtResponse = response.get();
|
||||
} catch (JedisDataException e) {
|
||||
builtResponse = e;
|
||||
}
|
||||
values.add(builtResponse);
|
||||
}
|
||||
return values;
|
||||
}
|
||||
@@ -69,13 +75,25 @@ public class Pipeline extends MultiKeyPipelineBase {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (isInMulti()) {
|
||||
discard();
|
||||
}
|
||||
|
||||
sync();
|
||||
}
|
||||
|
||||
public boolean isInMulti() {
|
||||
return currentMulti != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Syncronize pipeline by reading all responses. This operation close the
|
||||
* pipeline. In order to get return values from pipelined commands, capture
|
||||
* the different Response<?> of the commands you execute.
|
||||
*/
|
||||
public void sync() {
|
||||
List<Object> unformatted = client.getAll();
|
||||
List<Object> unformatted = client.getMany(getPipelinedResponseLength());
|
||||
for (Object o : unformatted) {
|
||||
generateResponse(o);
|
||||
}
|
||||
@@ -90,7 +108,7 @@ public class Pipeline extends MultiKeyPipelineBase {
|
||||
* @return A list of all the responses in the order you executed them.
|
||||
*/
|
||||
public List<Object> syncAndReturnAll() {
|
||||
List<Object> unformatted = client.getAll();
|
||||
List<Object> unformatted = client.getMany(getPipelinedResponseLength());
|
||||
List<Object> formatted = new ArrayList<Object>();
|
||||
|
||||
for (Object o : unformatted) {
|
||||
@@ -106,7 +124,6 @@ public class Pipeline extends MultiKeyPipelineBase {
|
||||
public Response<String> discard() {
|
||||
if (currentMulti == null)
|
||||
throw new JedisDataException("DISCARD without MULTI");
|
||||
|
||||
client.discard();
|
||||
currentMulti = null;
|
||||
return getResponse(BuilderFactory.STRING);
|
||||
|
||||
@@ -177,9 +177,9 @@ abstract class PipelineBase extends Queable implements BinaryRedisPipeline,
|
||||
return getResponse(BuilderFactory.BYTE_ARRAY);
|
||||
}
|
||||
|
||||
public Response<Long> getrange(byte[] key, long startOffset, long endOffset) {
|
||||
public Response<byte[]> getrange(byte[] key, long startOffset, long endOffset) {
|
||||
getClient(key).getrange(key, startOffset, endOffset);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
return getResponse(BuilderFactory.BYTE_ARRAY);
|
||||
}
|
||||
|
||||
public Response<Long> hdel(String key, String... field) {
|
||||
@@ -1026,6 +1026,56 @@ abstract class PipelineBase extends Queable implements BinaryRedisPipeline,
|
||||
return getResponse(BuilderFactory.DOUBLE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Long> zlexcount(final byte[] key, final byte[] min, final byte[] max) {
|
||||
getClient(key).zlexcount(key, min, max);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Long> zlexcount(final String key, final String min, final String max) {
|
||||
getClient(key).zlexcount(key, min, max);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] max, final byte[] min) {
|
||||
getClient(key).zrangeByLex(key, min, max);
|
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Set<String>> zrangeByLex(final String key, final String max, final String min) {
|
||||
getClient(key).zrangeByLex(key, min, max);
|
||||
return getResponse(BuilderFactory.STRING_ZSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Set<byte[]>> zrangeByLex(final byte[] key, final byte[] max,
|
||||
final byte[] min, final int offset, final int count) {
|
||||
getClient(key).zrangeByLex(key, min, max, offset, count);
|
||||
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Set<String>> zrangeByLex(final String key, final String max,
|
||||
final String min, final int offset, final int count) {
|
||||
getClient(key).zrangeByLex(key, min, max, offset, count);
|
||||
return getResponse(BuilderFactory.STRING_ZSET);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Long> zremrangeByLex(final byte[] key, final byte[] min, final byte[] max) {
|
||||
getClient(key).zremrangeByLex(key, min, max);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Response<Long> zremrangeByLex(final String key, final String min, final String max) {
|
||||
getClient(key).zremrangeByLex(key, min, max);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
}
|
||||
|
||||
public Response<Long> bitcount(String key) {
|
||||
getClient(key).bitcount(key);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
@@ -1098,16 +1148,6 @@ abstract class PipelineBase extends Queable implements BinaryRedisPipeline,
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Response<Long> pexpire(String key, int milliseconds) {
|
||||
return pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public Response<Long> pexpire(byte[] key, int milliseconds) {
|
||||
return pexpire(key, (long) milliseconds);
|
||||
}
|
||||
|
||||
public Response<Long> pexpire(String key, long milliseconds) {
|
||||
getClient(key).pexpire(key, milliseconds);
|
||||
return getResponse(BuilderFactory.LONG);
|
||||
|
||||
@@ -7,5 +7,9 @@ package redis.clients.jedis;
|
||||
* @see https://github.com/xetorthio/jedis/pull/498
|
||||
*/
|
||||
public abstract class PipelineBlock extends Pipeline {
|
||||
// For shadowing
|
||||
@SuppressWarnings("unused")
|
||||
private Client client;
|
||||
|
||||
public abstract void execute();
|
||||
}
|
||||
|
||||
@@ -59,6 +59,7 @@ public final class Protocol {
|
||||
public static final String CLUSTER_REPLICATE = "replicate";
|
||||
public static final String CLUSTER_SLAVES = "slaves";
|
||||
public static final String CLUSTER_FAILOVER = "failover";
|
||||
public static final String CLUSTER_SLOTS = "slots";
|
||||
public static final String PUBSUB_CHANNELS= "channels";
|
||||
public static final String PUBSUB_NUMSUB = "numsub";
|
||||
public static final String PUBSUB_NUM_PAT = "numpat";
|
||||
@@ -217,7 +218,7 @@ public final class Protocol {
|
||||
}
|
||||
|
||||
public static enum Command {
|
||||
PING, SET, GET, QUIT, EXISTS, DEL, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZCARD, ZSCORE, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, ZCOUNT, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, PFADD, PFCOUNT, PFMERGE;
|
||||
PING, SET, GET, QUIT, EXISTS, DEL, TYPE, FLUSHDB, KEYS, RANDOMKEY, RENAME, RENAMENX, RENAMEX, DBSIZE, EXPIRE, EXPIREAT, TTL, SELECT, MOVE, FLUSHALL, GETSET, MGET, SETNX, SETEX, MSET, MSETNX, DECRBY, DECR, INCRBY, INCR, APPEND, SUBSTR, HSET, HGET, HSETNX, HMSET, HMGET, HINCRBY, HEXISTS, HDEL, HLEN, HKEYS, HVALS, HGETALL, RPUSH, LPUSH, LLEN, LRANGE, LTRIM, LINDEX, LSET, LREM, LPOP, RPOP, RPOPLPUSH, SADD, SMEMBERS, SREM, SPOP, SMOVE, SCARD, SISMEMBER, SINTER, SINTERSTORE, SUNION, SUNIONSTORE, SDIFF, SDIFFSTORE, SRANDMEMBER, ZADD, ZRANGE, ZREM, ZINCRBY, ZRANK, ZREVRANK, ZREVRANGE, ZCARD, ZSCORE, MULTI, DISCARD, EXEC, WATCH, UNWATCH, SORT, BLPOP, BRPOP, AUTH, SUBSCRIBE, PUBLISH, UNSUBSCRIBE, PSUBSCRIBE, PUNSUBSCRIBE, PUBSUB, ZCOUNT, ZRANGEBYSCORE, ZREVRANGEBYSCORE, ZREMRANGEBYRANK, ZREMRANGEBYSCORE, ZUNIONSTORE, ZINTERSTORE, ZLEXCOUNT, ZRANGEBYLEX, ZREMRANGEBYLEX, SAVE, BGSAVE, BGREWRITEAOF, LASTSAVE, SHUTDOWN, INFO, MONITOR, SLAVEOF, CONFIG, STRLEN, SYNC, LPUSHX, PERSIST, RPUSHX, ECHO, LINSERT, DEBUG, BRPOPLPUSH, SETBIT, GETBIT, BITPOS, SETRANGE, GETRANGE, EVAL, EVALSHA, SCRIPT, SLOWLOG, OBJECT, BITCOUNT, BITOP, SENTINEL, DUMP, RESTORE, PEXPIRE, PEXPIREAT, PTTL, INCRBYFLOAT, PSETEX, CLIENT, TIME, MIGRATE, HINCRBYFLOAT, SCAN, HSCAN, SSCAN, ZSCAN, WAIT, CLUSTER, ASKING, PFADD, PFCOUNT, PFMERGE;
|
||||
|
||||
public final byte[] raw;
|
||||
|
||||
|
||||
@@ -24,4 +24,11 @@ public class Queable {
|
||||
return lr;
|
||||
}
|
||||
|
||||
protected boolean hasPipelinedResponse() {
|
||||
return pipelinedResponses.size() > 0;
|
||||
}
|
||||
|
||||
protected int getPipelinedResponseLength() {
|
||||
return pipelinedResponses.size();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,6 +184,15 @@ public interface RedisPipeline {
|
||||
Response<Long> zrevrank(String key, String member);
|
||||
|
||||
Response<Double> zscore(String key, String member);
|
||||
|
||||
Response<Long> zlexcount(final String key, final String min, final String max);
|
||||
|
||||
Response<Set<String>> zrangeByLex(final String key, final String max, final String min);
|
||||
|
||||
Response<Set<String>> zrangeByLex(final String key, final String max, final String min,
|
||||
final int offset, final int count);
|
||||
|
||||
Response<Long> zremrangeByLex(final String key, final String start, final String end);
|
||||
|
||||
Response<Long> bitcount(String key);
|
||||
|
||||
|
||||
@@ -8,16 +8,6 @@ public class ScanResult<T> {
|
||||
private byte[] cursor;
|
||||
private List<T> results;
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult(int cursor, List<T> results) {
|
||||
this(Protocol.toByteArray(cursor), results);
|
||||
}
|
||||
|
||||
public ScanResult(String cursor, List<T> results) {
|
||||
this(SafeEncoder.encode(cursor), results);
|
||||
}
|
||||
@@ -27,21 +17,7 @@ public class ScanResult<T> {
|
||||
this.results = results;
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
* @return int(currently), but will be changed to String, so be careful to prepare!
|
||||
*/
|
||||
public int getCursor() {
|
||||
return Integer.parseInt(getStringCursor());
|
||||
}
|
||||
|
||||
/**
|
||||
* FIXME: This method should be changed to getCursor() on next major release
|
||||
*/
|
||||
public String getStringCursor() {
|
||||
public String getCursor() {
|
||||
return SafeEncoder.encode(cursor);
|
||||
}
|
||||
|
||||
|
||||
@@ -125,12 +125,18 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
|
||||
Jedis j = getShard(arg);
|
||||
return j.blpop(arg);
|
||||
}
|
||||
|
||||
public List<String> blpop(int timeout,String key){
|
||||
Jedis j = getShard(key);
|
||||
return j.blpop(timeout,key);
|
||||
}
|
||||
public List<String> brpop(String arg) {
|
||||
Jedis j = getShard(arg);
|
||||
return j.brpop(arg);
|
||||
}
|
||||
|
||||
public List<String> brpop(int timeout,String key) {
|
||||
Jedis j = getShard(key);
|
||||
return j.brpop(timeout,key);
|
||||
}
|
||||
public Long decrBy(String key, long integer) {
|
||||
Jedis j = getShard(key);
|
||||
return j.decrBy(key, integer);
|
||||
@@ -346,6 +352,12 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
|
||||
return j.srandmember(key);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> srandmember(String key, int count) {
|
||||
Jedis j = getShard(key);
|
||||
return j.srandmember(key, count);
|
||||
}
|
||||
|
||||
public Long zadd(String key, double score, String member) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zadd(key, score, member);
|
||||
@@ -530,6 +542,27 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
|
||||
Jedis j = getShard(key);
|
||||
return j.zremrangeByScore(key, start, end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zlexcount(final String key, final String min, final String max) {
|
||||
return getShard(key).zlexcount(key, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max) {
|
||||
return getShard(key).zrangeByLex(key, min, max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> zrangeByLex(final String key, final String min, final String max,
|
||||
final int offset, final int count) {
|
||||
return getShard(key).zrangeByLex(key, min, max, offset, count);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long zremrangeByLex(final String key, final String min, final String max) {
|
||||
return getShard(key).zremrangeByLex(key, min, max);
|
||||
}
|
||||
|
||||
public Long linsert(String key, LIST_POSITION where, String pivot,
|
||||
String value) {
|
||||
@@ -547,41 +580,7 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
|
||||
return j.bitcount(key, start, end);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Entry<String, String>> hscan(String key, int cursor) {
|
||||
Jedis j = getShard(key);
|
||||
return j.hscan(key, cursor);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<String> sscan(String key, int cursor) {
|
||||
Jedis j = getShard(key);
|
||||
return j.sscan(key, cursor);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
/**
|
||||
* This method is deprecated due to bug (scan cursor should be unsigned long)
|
||||
* And will be removed on next major release
|
||||
* @see https://github.com/xetorthio/jedis/issues/531
|
||||
*/
|
||||
public ScanResult<Tuple> zscan(String key, int cursor) {
|
||||
Jedis j = getShard(key);
|
||||
return j.zscan(key, cursor);
|
||||
}
|
||||
|
||||
public ScanResult<Entry<String, String>> hscan(String key,
|
||||
final String cursor) {
|
||||
public ScanResult<Entry<String, String>> hscan(String key, final String cursor) {
|
||||
Jedis j = getShard(key);
|
||||
return j.hscan(key, cursor);
|
||||
}
|
||||
@@ -639,4 +638,5 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
|
||||
Jedis j = getShard(key);
|
||||
return j.pfcount(key);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -31,9 +31,16 @@ public class Transaction extends MultiKeyPipelineBase {
|
||||
return client;
|
||||
}
|
||||
|
||||
public void clear() {
|
||||
if (inTransaction) {
|
||||
discard();
|
||||
}
|
||||
}
|
||||
|
||||
public List<Object> exec() {
|
||||
// Discard QUEUED or ERROR
|
||||
client.getMany(getPipelinedResponseLength());
|
||||
client.exec();
|
||||
client.getAll(1); // Discard all but the last reply
|
||||
|
||||
List<Object> unformatted = client.getObjectMultiBulkReply();
|
||||
if (unformatted == null) {
|
||||
@@ -51,8 +58,9 @@ public class Transaction extends MultiKeyPipelineBase {
|
||||
}
|
||||
|
||||
public List<Response<?>> execGetResponse() {
|
||||
// Discard QUEUED or ERROR
|
||||
client.getMany(getPipelinedResponseLength());
|
||||
client.exec();
|
||||
client.getAll(1); // Discard all but the last reply
|
||||
|
||||
List<Object> unformatted = client.getObjectMultiBulkReply();
|
||||
if (unformatted == null) {
|
||||
@@ -66,11 +74,15 @@ public class Transaction extends MultiKeyPipelineBase {
|
||||
}
|
||||
|
||||
public String discard() {
|
||||
client.getMany(getPipelinedResponseLength());
|
||||
client.discard();
|
||||
client.getAll(1); // Discard all but the last reply
|
||||
inTransaction = false;
|
||||
clean();
|
||||
return client.getStatusCodeReply();
|
||||
}
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,6 +9,10 @@ import redis.clients.jedis.exceptions.JedisException;
|
||||
* @see https://github.com/xetorthio/jedis/pull/498
|
||||
*/
|
||||
public abstract class TransactionBlock extends Transaction {
|
||||
// For shadowing
|
||||
@SuppressWarnings("unused")
|
||||
private Client client;
|
||||
|
||||
public TransactionBlock(Client client) {
|
||||
super(client);
|
||||
}
|
||||
@@ -19,6 +23,6 @@ public abstract class TransactionBlock extends Transaction {
|
||||
public abstract void execute() throws JedisException;
|
||||
|
||||
public void setClient(Client client) {
|
||||
this.client = client;
|
||||
super.setClient(client);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,9 +23,15 @@ public class ZParams {
|
||||
|
||||
private List<byte[]> params = new ArrayList<byte[]>();
|
||||
|
||||
public ZParams weights(final int... weights) {
|
||||
/**
|
||||
* Set weights.
|
||||
*
|
||||
* @param weights
|
||||
* weights.
|
||||
*/
|
||||
public ZParams weights(final double... weights) {
|
||||
params.add(WEIGHTS.raw);
|
||||
for (final int weight : weights) {
|
||||
for (final double weight : weights) {
|
||||
params.add(Protocol.toByteArray(weight));
|
||||
}
|
||||
|
||||
|
||||
@@ -3,7 +3,6 @@ package redis.clients.util;
|
||||
import redis.clients.jedis.HostAndPort;
|
||||
|
||||
public class ClusterNodeInformationParser {
|
||||
private static final String HOST_MYSELF_IDENTIFIER = ":0";
|
||||
private static final String SLOT_IMPORT_IDENTIFIER = "-<-";
|
||||
private static final String SLOT_IN_TRANSITION_IDENTIFIER = "[";
|
||||
public static final int SLOT_INFORMATIONS_START_INDEX = 8;
|
||||
@@ -36,13 +35,13 @@ public class ClusterNodeInformationParser {
|
||||
public HostAndPort getHostAndPortFromNodeLine(String[] nodeInfoPartArray,
|
||||
HostAndPort current) {
|
||||
String stringHostAndPort = nodeInfoPartArray[HOST_AND_PORT_INDEX];
|
||||
if (HOST_MYSELF_IDENTIFIER.equals(stringHostAndPort)) {
|
||||
return current;
|
||||
}
|
||||
|
||||
String[] arrayHostAndPort = stringHostAndPort.split(":");
|
||||
return new HostAndPort(arrayHostAndPort[0],
|
||||
Integer.valueOf(arrayHostAndPort[1]));
|
||||
return new HostAndPort(
|
||||
arrayHostAndPort[0].isEmpty() ? current.getHost()
|
||||
: arrayHostAndPort[0],
|
||||
arrayHostAndPort[1].isEmpty() ? current.getPort() : Integer
|
||||
.valueOf(arrayHostAndPort[1]));
|
||||
}
|
||||
|
||||
private void fillSlotInformation(String[] slotInfoPartArray,
|
||||
|
||||
26
src/main/java/redis/clients/util/JedisURIHelper.java
Normal file
26
src/main/java/redis/clients/util/JedisURIHelper.java
Normal file
@@ -0,0 +1,26 @@
|
||||
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) {
|
||||
String dbIndexStr = pathSplit[1];
|
||||
if (dbIndexStr.isEmpty()) {
|
||||
return 0;
|
||||
}
|
||||
return Integer.parseInt(dbIndexStr);
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,7 @@
|
||||
package redis.clients.util;
|
||||
|
||||
import java.io.Closeable;
|
||||
|
||||
import org.apache.commons.pool2.PooledObjectFactory;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPool;
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
@@ -7,7 +9,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
import redis.clients.jedis.exceptions.JedisException;
|
||||
|
||||
public abstract class Pool<T> {
|
||||
public abstract class Pool<T> implements Closeable {
|
||||
protected GenericObjectPool<T> internalPool;
|
||||
|
||||
/**
|
||||
@@ -17,6 +19,15 @@ public abstract class Pool<T> {
|
||||
public Pool() {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
closeInternalPool();
|
||||
}
|
||||
|
||||
public boolean isClosed() {
|
||||
return this.internalPool.isClosed();
|
||||
}
|
||||
|
||||
public Pool(final GenericObjectPoolConfig poolConfig,
|
||||
PooledObjectFactory<T> factory) {
|
||||
initPool(poolConfig, factory);
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
package redis.clients.jedis.tests;
|
||||
|
||||
import org.junit.After;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
import redis.clients.jedis.Connection;
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
|
||||
public class ConnectionCloseTest extends Assert {
|
||||
|
||||
private Connection client;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
client = new Connection();
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown() throws Exception {
|
||||
client.close();
|
||||
}
|
||||
|
||||
@Test(expected = JedisConnectionException.class)
|
||||
public void checkUnkownHost() {
|
||||
client.setHost("someunknownhost");
|
||||
client.connect();
|
||||
}
|
||||
|
||||
@Test(expected = JedisConnectionException.class)
|
||||
public void checkWrongPort() {
|
||||
client.setHost("localhost");
|
||||
client.setPort(55665);
|
||||
client.connect();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void connectIfNotConnectedWhenSettingTimeoutInfinite() {
|
||||
client.setHost("localhost");
|
||||
client.setPort(6379);
|
||||
client.setTimeoutInfinite();
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ public class HostAndPortUtil {
|
||||
sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT));
|
||||
sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 1));
|
||||
sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 2));
|
||||
sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 3));
|
||||
|
||||
clusterHostAndPortList.add(new HostAndPort("localhost", 7379));
|
||||
clusterHostAndPortList.add(new HostAndPort("localhost", 7380));
|
||||
|
||||
@@ -17,7 +17,7 @@ public class JedisClusterNodeInformationParserTest extends Assert {
|
||||
|
||||
@Test
|
||||
public void testParseNodeMyself() {
|
||||
String nodeInfo = "9b0d2ab38ee31482c95fdb2c7847a0d40e88d518 :0 myself,master - 0 0 1 connected 0-5460";
|
||||
String nodeInfo = "9b0d2ab38ee31482c95fdb2c7847a0d40e88d518 :7379 myself,master - 0 0 1 connected 0-5460";
|
||||
HostAndPort current = new HostAndPort("localhost", 7379);
|
||||
ClusterNodeInformation clusterNodeInfo = parser
|
||||
.parse(nodeInfo, current);
|
||||
@@ -44,7 +44,7 @@ public class JedisClusterNodeInformationParserTest extends Assert {
|
||||
|
||||
@Test
|
||||
public void testParseSlotBeingMigrated() {
|
||||
String nodeInfo = "5f4a2236d00008fba7ac0dd24b95762b446767bd :0 myself,master - 0 0 1 connected 0-5459 [5460->-5f4a2236d00008fba7ac0dd24b95762b446767bd] [5461-<-5f4a2236d00008fba7ac0dd24b95762b446767bd]";
|
||||
String nodeInfo = "5f4a2236d00008fba7ac0dd24b95762b446767bd :7379 myself,master - 0 0 1 connected 0-5459 [5460->-5f4a2236d00008fba7ac0dd24b95762b446767bd] [5461-<-5f4a2236d00008fba7ac0dd24b95762b446767bd]";
|
||||
HostAndPort current = new HostAndPort("localhost", 7379);
|
||||
ClusterNodeInformation clusterNodeInfo = parser
|
||||
.parse(nodeInfo, current);
|
||||
|
||||
@@ -2,6 +2,7 @@ package redis.clients.jedis.tests;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -15,7 +16,13 @@ import org.junit.Test;
|
||||
import redis.clients.jedis.HostAndPort;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.JedisCluster;
|
||||
import redis.clients.jedis.exceptions.*;
|
||||
import redis.clients.jedis.JedisPool;
|
||||
import redis.clients.jedis.exceptions.JedisAskDataException;
|
||||
import redis.clients.jedis.exceptions.JedisClusterException;
|
||||
import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException;
|
||||
import redis.clients.jedis.exceptions.JedisConnectionException;
|
||||
import redis.clients.jedis.exceptions.JedisException;
|
||||
import redis.clients.jedis.exceptions.JedisMovedDataException;
|
||||
import redis.clients.jedis.tests.utils.JedisClusterTestUtil;
|
||||
import redis.clients.util.JedisClusterCRC16;
|
||||
|
||||
@@ -329,6 +336,33 @@ public class JedisClusterTest extends Assert {
|
||||
jc.set("52", "poolTestValue");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCloseable() {
|
||||
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
|
||||
jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));
|
||||
|
||||
JedisCluster jc = null;
|
||||
try {
|
||||
jc = new JedisCluster(jedisClusterNode);
|
||||
jc.set("51", "foo");
|
||||
} finally {
|
||||
if (jc != null) {
|
||||
jc.close();
|
||||
}
|
||||
}
|
||||
|
||||
Iterator<JedisPool> poolIterator = jc.getClusterNodes().values().iterator();
|
||||
while (poolIterator.hasNext()) {
|
||||
JedisPool pool = poolIterator.next();
|
||||
try {
|
||||
pool.getResource();
|
||||
fail("JedisCluster's internal pools should be already destroyed");
|
||||
} catch (JedisConnectionException e) {
|
||||
// ok to go...
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static String getNodeServingSlotRange(String infoOutput) {
|
||||
// f4f3dc4befda352a4e0beccf29f5e8828438705d 127.0.0.1:7380 master - 0 1394372400827 0 connected 5461-10922
|
||||
for (String infoLine : infoOutput.split("\n")) {
|
||||
|
||||
@@ -27,6 +27,20 @@ public class JedisPoolTest extends Assert {
|
||||
assertEquals("bar", jedis.get("foo"));
|
||||
pool.returnResource(jedis);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCloseableConnections() throws Exception {
|
||||
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.close();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -39,6 +53,7 @@ public class JedisPoolTest extends Assert {
|
||||
assertEquals("bar", jedis.get("foo"));
|
||||
pool.returnResource(jedis);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -56,6 +71,7 @@ public class JedisPoolTest extends Assert {
|
||||
jedis.incr("foo");
|
||||
pool.returnResource(jedis);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -72,6 +88,7 @@ public class JedisPoolTest extends Assert {
|
||||
jedis.incr("foo");
|
||||
pool.returnResource(jedis);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test(expected = JedisConnectionException.class)
|
||||
@@ -99,6 +116,7 @@ public class JedisPoolTest extends Assert {
|
||||
jedis.set("foo", "bar");
|
||||
pool.returnResource(jedis);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -110,6 +128,7 @@ public class JedisPoolTest extends Assert {
|
||||
assertEquals("bar", jedis0.get("foo"));
|
||||
pool0.returnResource(jedis0);
|
||||
pool0.destroy();
|
||||
assertTrue(pool0.isClosed());
|
||||
|
||||
JedisPool pool1 = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
|
||||
hnp.getPort(), 2000, "foobared", 1);
|
||||
@@ -117,6 +136,7 @@ public class JedisPoolTest extends Assert {
|
||||
assertNull(jedis1.get("foo"));
|
||||
pool1.returnResource(jedis1);
|
||||
pool1.destroy();
|
||||
assertTrue(pool1.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -144,6 +164,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(),
|
||||
@@ -163,6 +189,7 @@ public class JedisPoolTest extends Assert {
|
||||
|
||||
pool.returnResource(jedis1);
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -176,6 +203,7 @@ public class JedisPoolTest extends Assert {
|
||||
|
||||
pool0.returnResource(jedis);
|
||||
pool0.destroy();
|
||||
assertTrue(pool0.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -204,6 +232,7 @@ public class JedisPoolTest extends Assert {
|
||||
}
|
||||
|
||||
pool.destroy();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -238,4 +267,40 @@ public class JedisPoolTest extends Assert {
|
||||
pool.returnResource(null);
|
||||
pool.returnResourceObject(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNumActiveIsNegativeWhenPoolIsClosed() {
|
||||
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
|
||||
hnp.getPort(), 2000, "foobared", 0, "my_shiny_client_name");
|
||||
|
||||
pool.destroy();
|
||||
assertTrue(pool.getNumActive() < 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void getNumActiveReturnsTheCorrectNumber() {
|
||||
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"));
|
||||
|
||||
assertEquals(1, pool.getNumActive());
|
||||
|
||||
Jedis jedis2 = pool.getResource();
|
||||
jedis.auth("foobared");
|
||||
jedis.set("foo", "bar");
|
||||
|
||||
assertEquals(2, pool.getNumActive());
|
||||
|
||||
pool.returnResource(jedis);
|
||||
assertEquals(1, pool.getNumActive());
|
||||
|
||||
pool.returnResource(jedis2);
|
||||
|
||||
assertEquals(0, pool.getNumActive());
|
||||
|
||||
pool.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package redis.clients.jedis.tests;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
|
||||
import org.junit.Before;
|
||||
@@ -21,18 +22,63 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
.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(3);
|
||||
|
||||
protected static Jedis sentinelJedis1;
|
||||
protected static Jedis sentinelJedis2;
|
||||
|
||||
protected Set<String> sentinels = new HashSet<String>();
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
sentinels.add(sentinel1.toString());
|
||||
sentinels.add(sentinel2.toString());
|
||||
|
||||
sentinelJedis1 = new Jedis(sentinel1.getHost(), sentinel1.getPort());
|
||||
sentinelJedis2 = new Jedis(sentinel2.getHost(), sentinel2.getPort());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void errorMasterNameNotThrowException() throws InterruptedException {
|
||||
final String wrongMasterName = "wrongMasterName";
|
||||
new Thread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
TimeUnit.SECONDS.sleep(3);
|
||||
sentinelJedis1.sentinelMonitor(wrongMasterName,
|
||||
"127.0.0.1", master.getPort(), 2);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
}
|
||||
}).start();
|
||||
|
||||
JedisSentinelPool pool = new JedisSentinelPool(wrongMasterName,
|
||||
sentinels);
|
||||
pool.destroy();
|
||||
sentinelJedis1.sentinelRemove(wrongMasterName);
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void checkCloseableConnections() throws Exception {
|
||||
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
|
||||
|
||||
JedisSentinelPool pool = new JedisSentinelPool(
|
||||
MASTER_NAME, sentinels, config, 1000, "foobared", 2);
|
||||
Jedis jedis = pool.getResource();
|
||||
jedis.auth("foobared");
|
||||
jedis.set("foo", "bar");
|
||||
assertEquals("bar", jedis.get("foo"));
|
||||
pool.returnResource(jedis);
|
||||
pool.close();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -41,6 +87,8 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
new GenericObjectPoolConfig(), 1000, "foobared", 2);
|
||||
|
||||
forceFailover(pool);
|
||||
// after failover sentinel needs a bit of time to stabilize before a new failover
|
||||
Thread.sleep(100);
|
||||
forceFailover(pool);
|
||||
|
||||
// you can test failover as much as possible
|
||||
@@ -134,29 +182,25 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
HostAndPort oldMaster = pool.getCurrentHostMaster();
|
||||
|
||||
// jedis connection should be master
|
||||
Jedis jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
Jedis beforeFailoverJedis = pool.getResource();
|
||||
assertEquals("PONG", beforeFailoverJedis.ping());
|
||||
|
||||
// It can throw JedisDataException while there's no slave to promote
|
||||
// There's nothing we can do, so we just pass Exception to make test
|
||||
// fail fast
|
||||
sentinelJedis1.sentinelFailover(MASTER_NAME);
|
||||
|
||||
waitForFailover(pool, oldMaster);
|
||||
// JedisSentinelPool recognize master but may not changed internal pool
|
||||
// yet
|
||||
Thread.sleep(100);
|
||||
|
||||
Jedis afterFailoverJedis = pool.getResource();
|
||||
assertEquals("PONG", afterFailoverJedis.ping());
|
||||
assertEquals("foobared", afterFailoverJedis.configGet("requirepass").get(1));
|
||||
assertEquals(2, afterFailoverJedis.getDB().intValue());
|
||||
|
||||
jedis = pool.getResource();
|
||||
assertEquals("PONG", jedis.ping());
|
||||
assertEquals("foobared", jedis.configGet("requirepass").get(1));
|
||||
assertEquals(2, jedis.getDB().intValue());
|
||||
// returning both connections to the pool should not throw
|
||||
beforeFailoverJedis.close();
|
||||
afterFailoverJedis.close();
|
||||
}
|
||||
|
||||
private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster)
|
||||
throws InterruptedException {
|
||||
HostAndPort newMaster = JedisSentinelTestUtil
|
||||
.waitForNewPromotedMaster(sentinelJedis1);
|
||||
.waitForNewPromotedMaster(MASTER_NAME, sentinelJedis1, sentinelJedis2);
|
||||
|
||||
waitForJedisSentinelPoolRecognizeNewMaster(pool, newMaster);
|
||||
}
|
||||
@@ -166,10 +210,9 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
throws InterruptedException {
|
||||
|
||||
while (true) {
|
||||
String host = pool.getCurrentHostMaster().getHost();
|
||||
int port = pool.getCurrentHostMaster().getPort();
|
||||
HostAndPort currentHostMaster = pool.getCurrentHostMaster();
|
||||
|
||||
if (host.equals(newMaster.getHost()) && port == newMaster.getPort())
|
||||
if (newMaster.equals(currentHostMaster))
|
||||
break;
|
||||
|
||||
System.out
|
||||
@@ -179,4 +222,4 @@ public class JedisSentinelPoolTest extends JedisTestBase {
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -85,16 +85,16 @@ public class JedisSentinelTest extends JedisTestBase {
|
||||
public void sentinelFailover() throws InterruptedException {
|
||||
Jedis j = new Jedis(sentinelForFailover.getHost(),
|
||||
sentinelForFailover.getPort());
|
||||
Jedis j2 = new Jedis(sentinelForFailover.getHost(),
|
||||
sentinelForFailover.getPort());
|
||||
|
||||
try {
|
||||
List<String> masterHostAndPort = j
|
||||
.sentinelGetMasterAddrByName(FAILOVER_MASTER_NAME);
|
||||
HostAndPort currentMaster = new HostAndPort(masterHostAndPort.get(0),
|
||||
Integer.parseInt(masterHostAndPort.get(1)));
|
||||
String result = j.sentinelFailover(FAILOVER_MASTER_NAME);
|
||||
assertEquals("OK", result);
|
||||
|
||||
JedisSentinelTestUtil.waitForNewPromotedMaster(j);
|
||||
JedisSentinelTestUtil.waitForNewPromotedMaster(FAILOVER_MASTER_NAME, j, j2);
|
||||
|
||||
masterHostAndPort = j
|
||||
.sentinelGetMasterAddrByName(FAILOVER_MASTER_NAME);
|
||||
|
||||
@@ -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,22 @@ 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");
|
||||
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);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCloseable() {
|
||||
jedis.close();
|
||||
|
||||
@@ -1,24 +1,14 @@
|
||||
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.HostAndPort;
|
||||
import redis.clients.jedis.Jedis;
|
||||
import redis.clients.jedis.Pipeline;
|
||||
import redis.clients.jedis.Response;
|
||||
import redis.clients.jedis.Tuple;
|
||||
import redis.clients.jedis.*;
|
||||
import redis.clients.jedis.exceptions.JedisDataException;
|
||||
|
||||
import java.io.UnsupportedEncodingException;
|
||||
import java.util.*;
|
||||
|
||||
public class PipeliningTest extends Assert {
|
||||
private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);
|
||||
|
||||
@@ -52,6 +42,9 @@ public class PipeliningTest extends Assert {
|
||||
jedis.hset("hash", "foo", "bar");
|
||||
jedis.zadd("zset", 1, "foo");
|
||||
jedis.sadd("set", "foo");
|
||||
jedis.setrange("setrange", 0, "0123456789");
|
||||
byte[] bytesForSetRange = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9};
|
||||
jedis.setrange("setrangebytes".getBytes(), 0, bytesForSetRange);
|
||||
|
||||
Pipeline p = jedis.pipelined();
|
||||
Response<String> string = p.get("string");
|
||||
@@ -68,8 +61,10 @@ public class PipeliningTest extends Assert {
|
||||
p.sadd("set", "foo");
|
||||
Response<Set<String>> smembers = p.smembers("set");
|
||||
Response<Set<Tuple>> zrangeWithScores = p.zrangeWithScores("zset", 0,
|
||||
-1);
|
||||
p.sync();
|
||||
-1);
|
||||
Response<String> getrange = p.getrange("setrange", 1, 3);
|
||||
Response<byte[]> getrangeBytes = p.getrange("setrangebytes".getBytes(), 6, 8);
|
||||
p.sync();
|
||||
|
||||
assertEquals("foo", string.get());
|
||||
assertEquals("foo", list.get());
|
||||
@@ -83,6 +78,9 @@ public class PipeliningTest extends Assert {
|
||||
assertNotNull(hgetAll.get().get("foo"));
|
||||
assertEquals(1, smembers.get().size());
|
||||
assertEquals(1, zrangeWithScores.get().size());
|
||||
assertEquals("123", getrange.get());
|
||||
byte[] expectedGetRangeBytes = {6, 7, 8};
|
||||
assertArrayEquals(expectedGetRangeBytes, getrangeBytes.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -373,4 +371,79 @@ public class PipeliningTest extends Assert {
|
||||
assertNull(result1.get());
|
||||
assertEquals("13", result2.get());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testPipelinedTransactionResponse() {
|
||||
|
||||
String key1 = "key1";
|
||||
String val1 = "val1";
|
||||
|
||||
String key2 = "key2";
|
||||
String val2 = "val2";
|
||||
|
||||
String key3 = "key3";
|
||||
String field1 = "field1";
|
||||
String field2 = "field2";
|
||||
String field3 = "field3";
|
||||
String field4 = "field4";
|
||||
|
||||
String value1 = "value1";
|
||||
String value2 = "value2";
|
||||
String value3 = "value3";
|
||||
String value4 = "value4";
|
||||
|
||||
Map<String, String> hashMap = new HashMap<String, String>();
|
||||
hashMap.put(field1, value1);
|
||||
hashMap.put(field2, value2);
|
||||
|
||||
String key4 = "key4";
|
||||
Map<String, String> hashMap1 = new HashMap<String, String>();
|
||||
hashMap1.put(field3, value3);
|
||||
hashMap1.put(field4, value4);
|
||||
|
||||
|
||||
jedis.set(key1, val1);
|
||||
jedis.set(key2, val2);
|
||||
jedis.hmset(key3, hashMap);
|
||||
jedis.hmset(key4, hashMap1);
|
||||
|
||||
Pipeline pipeline = jedis.pipelined();
|
||||
pipeline.multi();
|
||||
|
||||
pipeline.get(key1);
|
||||
pipeline.hgetAll(key2);
|
||||
pipeline.hgetAll(key3);
|
||||
pipeline.get(key4);
|
||||
|
||||
Response<List<Object> > response = pipeline.exec();
|
||||
pipeline.sync();
|
||||
|
||||
List<Object> result = response.get();
|
||||
|
||||
assertEquals(4, result.size());
|
||||
|
||||
assertEquals("val1", result.get(0));
|
||||
|
||||
assertTrue(result.get(1) instanceof JedisDataException);
|
||||
|
||||
Map<String, String> hashMapReceived = (Map<String, String>)result.get(2);
|
||||
Iterator<String> iterator = hashMapReceived.keySet().iterator();
|
||||
String mapKey1 = iterator.next();
|
||||
String mapKey2 = iterator.next();
|
||||
assertFalse(iterator.hasNext());
|
||||
verifyHasBothValues(mapKey1, mapKey2, field1, field2);
|
||||
String mapValue1 = hashMapReceived.get(mapKey1);
|
||||
String mapValue2 = hashMapReceived.get(mapKey2);
|
||||
verifyHasBothValues(mapValue1, mapValue2, value1, value2);
|
||||
|
||||
assertTrue(result.get(3) instanceof JedisDataException);
|
||||
}
|
||||
|
||||
private void verifyHasBothValues(String firstKey, String secondKey, String value1, String value2) {
|
||||
assertFalse(firstKey.equals(secondKey));
|
||||
assertTrue(firstKey.equals(value1)
|
||||
|| firstKey.equals(value2));
|
||||
assertTrue(secondKey.equals(value1)
|
||||
|| secondKey.equals(value2));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -55,6 +55,18 @@ public class ShardedJedisPoolTest extends Assert {
|
||||
pool.destroy();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkCloseableConnections() throws Exception {
|
||||
ShardedJedisPool pool = new ShardedJedisPool(
|
||||
new GenericObjectPoolConfig(), shards);
|
||||
ShardedJedis jedis = pool.getResource();
|
||||
jedis.set("foo", "bar");
|
||||
assertEquals("bar", jedis.get("foo"));
|
||||
pool.returnResource(jedis);
|
||||
pool.close();
|
||||
assertTrue(pool.isClosed());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void checkConnectionWithDefaultPort() {
|
||||
ShardedJedisPool pool = new ShardedJedisPool(
|
||||
|
||||
@@ -521,7 +521,7 @@ public class AllKindOfValuesCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
ScanResult<String> result = jedis.scan(SCAN_POINTER_START);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
@@ -541,7 +541,7 @@ public class AllKindOfValuesCommandsTest extends JedisCommandTestBase {
|
||||
jedis.set("aa", "aa");
|
||||
ScanResult<String> result = jedis.scan(SCAN_POINTER_START, params);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
|
||||
@@ -45,6 +45,8 @@ public class ClusterCommandsTest extends JedisTestBase {
|
||||
node1.clusterDelSlots(1, 2, 3, 4, 5, 500);
|
||||
node1.clusterSetSlotNode(5000, node1Id);
|
||||
node1.clusterDelSlots(5000, 10000);
|
||||
node1.clusterDelSlots(3000, 3001, 3002);
|
||||
node2.clusterDelSlots(4000, 4001, 4002);
|
||||
node1.clusterAddSlots(6000);
|
||||
node1.clusterDelSlots(6000);
|
||||
waitForGossip();
|
||||
@@ -134,5 +136,34 @@ public class ClusterCommandsTest extends JedisTestBase {
|
||||
String status = node1.clusterSetSlotMigrating(5000, nodeId);
|
||||
assertEquals("OK", status);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void clusterSlots() {
|
||||
// please see cluster slot output format from below commit
|
||||
// @see:
|
||||
// https://github.com/antirez/redis/commit/e14829de3025ffb0d3294e5e5a1553afd9f10b60
|
||||
String status = node1.clusterAddSlots(3000, 3001, 3002);
|
||||
assertEquals("OK", status);
|
||||
status = node2.clusterAddSlots(4000, 4001, 4002);
|
||||
assertEquals("OK", status);
|
||||
|
||||
List<Object> slots = node1.clusterSlots();
|
||||
assertNotNull(slots);
|
||||
assertTrue(slots.size() > 0);
|
||||
|
||||
for (Object slotInfoObj : slots) {
|
||||
List<Object> slotInfo = (List<Object>) slotInfoObj;
|
||||
assertNotNull(slots);
|
||||
assertTrue(slots.size() >= 2);
|
||||
|
||||
assertTrue(slotInfo.get(0) instanceof Long);
|
||||
assertTrue(slotInfo.get(1) instanceof Long);
|
||||
|
||||
if (slots.size() > 2) {
|
||||
// assigned slots
|
||||
assertTrue(slotInfo.get(2) instanceof List);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -9,9 +9,11 @@ import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import org.junit.Test;
|
||||
|
||||
import redis.clients.jedis.Pipeline;
|
||||
import redis.clients.jedis.Response;
|
||||
import redis.clients.jedis.ScanParams;
|
||||
import redis.clients.jedis.ScanResult;
|
||||
|
||||
import static redis.clients.jedis.ScanParams.SCAN_POINTER_START;
|
||||
import static redis.clients.jedis.ScanParams.SCAN_POINTER_START_BINARY;
|
||||
|
||||
@@ -316,6 +318,22 @@ public class HashesCommandsTest extends JedisCommandTestBase {
|
||||
assertArrayEquals(bbar, bhash.get(bcar));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hgetAllPipeline() {
|
||||
Map<byte[], byte[]> bh = new HashMap<byte[], byte[]>();
|
||||
bh.put(bbar, bcar);
|
||||
bh.put(bcar, bbar);
|
||||
jedis.hmset(bfoo, bh);
|
||||
Pipeline pipeline = jedis.pipelined();
|
||||
Response<Map<byte[], byte[]>> bhashResponse = pipeline.hgetAll(bfoo);
|
||||
pipeline.sync();
|
||||
Map<byte[], byte[]> bhash = bhashResponse.get();
|
||||
|
||||
assertEquals(2, bhash.size());
|
||||
assertArrayEquals(bcar, bhash.get(bbar));
|
||||
assertArrayEquals(bbar, bhash.get(bcar));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void hscan() {
|
||||
jedis.hset("foo", "b", "b");
|
||||
@@ -323,7 +341,7 @@ public class HashesCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
ScanResult<Map.Entry<String, String>> result = jedis.hscan("foo", SCAN_POINTER_START);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
@@ -346,7 +364,7 @@ public class HashesCommandsTest extends JedisCommandTestBase {
|
||||
ScanResult<Map.Entry<String, String>> result = jedis.hscan("foo",
|
||||
SCAN_POINTER_START, params);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
|
||||
@@ -466,7 +466,7 @@ public class SetCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
ScanResult<String> result = jedis.sscan("foo", SCAN_POINTER_START);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
@@ -486,7 +486,7 @@ public class SetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.sadd("foo", "b", "a", "aa");
|
||||
ScanResult<String> result = jedis.sscan("foo", SCAN_POINTER_START, params);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
|
||||
@@ -20,6 +20,10 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
final byte[] ba = { 0x0A };
|
||||
final byte[] bb = { 0x0B };
|
||||
final byte[] bc = { 0x0C };
|
||||
final byte[] bInclusiveB = { 0x5B, 0x0B };
|
||||
final byte[] bExclusiveC = { 0x28, 0x0C };
|
||||
final byte[] bLexMinusInf = { 0x2D };
|
||||
final byte[] bLexPlusInf = { 0x2B };
|
||||
|
||||
final byte[] bbar1 = { 0x05, 0x06, 0x07, 0x08, 0x0A };
|
||||
final byte[] bbar2 = { 0x05, 0x06, 0x07, 0x08, 0x0B };
|
||||
@@ -54,7 +58,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
assertEquals(0, bstatus);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void zrange() {
|
||||
jedis.zadd("foo", 1d, "a");
|
||||
@@ -91,6 +95,48 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
assertEquals(bexpected, brange);
|
||||
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zrangeByLex() {
|
||||
jedis.zadd("foo", 1, "aa");
|
||||
jedis.zadd("foo", 1, "c");
|
||||
jedis.zadd("foo", 1, "bb");
|
||||
jedis.zadd("foo", 1, "d");
|
||||
|
||||
Set<String> expected = new LinkedHashSet<String>();
|
||||
expected.add("bb");
|
||||
expected.add("c");
|
||||
|
||||
// exclusive aa ~ inclusive c
|
||||
assertEquals(expected, jedis.zrangeByLex("foo", "(aa", "[c"));
|
||||
|
||||
expected.clear();
|
||||
expected.add("bb");
|
||||
expected.add("c");
|
||||
|
||||
// with LIMIT
|
||||
assertEquals(expected, jedis.zrangeByLex("foo", "-", "+", 1, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zrangeByLexBinary() {
|
||||
// binary
|
||||
jedis.zadd(bfoo, 1, ba);
|
||||
jedis.zadd(bfoo, 1, bc);
|
||||
jedis.zadd(bfoo, 1, bb);
|
||||
|
||||
Set<byte[]> bExpected = new LinkedHashSet<byte[]>();
|
||||
bExpected.add(bb);
|
||||
|
||||
assertEquals(bExpected, jedis.zrangeByLex(bfoo, bInclusiveB, bExclusiveC));
|
||||
|
||||
bExpected.clear();
|
||||
bExpected.add(ba);
|
||||
bExpected.add(bb);
|
||||
|
||||
// with LIMIT
|
||||
assertEquals(bExpected, jedis.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf, 0, 2));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zrevrange() {
|
||||
@@ -401,6 +447,40 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
assertEquals(3, bresult);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zlexcount() {
|
||||
jedis.zadd("foo", 1, "a");
|
||||
jedis.zadd("foo", 1, "b");
|
||||
jedis.zadd("foo", 1, "c");
|
||||
jedis.zadd("foo", 1, "aa");
|
||||
|
||||
long result = jedis.zlexcount("foo", "[aa", "(c");
|
||||
assertEquals(2, result);
|
||||
|
||||
result = jedis.zlexcount("foo", "-", "+");
|
||||
assertEquals(4, result);
|
||||
|
||||
result = jedis.zlexcount("foo", "-", "(c");
|
||||
assertEquals(3, result);
|
||||
|
||||
result = jedis.zlexcount("foo", "[aa", "+");
|
||||
assertEquals(3, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zlexcountBinary() {
|
||||
// Binary
|
||||
jedis.zadd(bfoo, 1, ba);
|
||||
jedis.zadd(bfoo, 1, bc);
|
||||
jedis.zadd(bfoo, 1, bb);
|
||||
|
||||
long result = jedis.zlexcount(bfoo, bInclusiveB, bExclusiveC);
|
||||
assertEquals(1, result);
|
||||
|
||||
result = jedis.zlexcount(bfoo, bLexMinusInf, bLexPlusInf);
|
||||
assertEquals(3, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zrangebyscore() {
|
||||
@@ -739,6 +819,41 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
assertEquals(bexpected, jedis.zrange(bfoo, 0, 100));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zremrangeByLex() {
|
||||
jedis.zadd("foo", 1, "a");
|
||||
jedis.zadd("foo", 1, "b");
|
||||
jedis.zadd("foo", 1, "c");
|
||||
jedis.zadd("foo", 1, "aa");
|
||||
|
||||
long result = jedis.zremrangeByLex("foo", "[aa", "(c");
|
||||
|
||||
assertEquals(2, result);
|
||||
|
||||
Set<String> expected = new LinkedHashSet<String>();
|
||||
expected.add("a");
|
||||
expected.add("c");
|
||||
|
||||
assertEquals(expected, jedis.zrangeByLex("foo", "-", "+"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zremrangeByLexBinary() {
|
||||
jedis.zadd(bfoo, 1, ba);
|
||||
jedis.zadd(bfoo, 1, bc);
|
||||
jedis.zadd(bfoo, 1, bb);
|
||||
|
||||
long bresult = jedis.zremrangeByLex(bfoo, bInclusiveB, bExclusiveC);
|
||||
|
||||
assertEquals(1, bresult);
|
||||
|
||||
Set<byte[]> bexpected = new LinkedHashSet<byte[]>();
|
||||
bexpected.add(ba);
|
||||
bexpected.add(bc);
|
||||
|
||||
assertEquals(bexpected, jedis.zrangeByLex(bfoo, bLexMinusInf, bLexPlusInf));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zunionstore() {
|
||||
@@ -783,15 +898,15 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.zadd("bar", 2, "b");
|
||||
|
||||
ZParams params = new ZParams();
|
||||
params.weights(2, 2);
|
||||
params.weights(2, 2.5);
|
||||
params.aggregate(ZParams.Aggregate.SUM);
|
||||
long result = jedis.zunionstore("dst", params, "foo", "bar");
|
||||
|
||||
assertEquals(2, result);
|
||||
|
||||
Set<Tuple> expected = new LinkedHashSet<Tuple>();
|
||||
expected.add(new Tuple("b", new Double(8)));
|
||||
expected.add(new Tuple("a", new Double(6)));
|
||||
expected.add(new Tuple("b", new Double(9)));
|
||||
expected.add(new Tuple("a", new Double(7)));
|
||||
|
||||
assertEquals(expected, jedis.zrangeWithScores("dst", 0, 100));
|
||||
|
||||
@@ -802,7 +917,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.zadd(bbar, 2, bb);
|
||||
|
||||
ZParams bparams = new ZParams();
|
||||
bparams.weights(2, 2);
|
||||
bparams.weights(2, 2.5);
|
||||
bparams.aggregate(ZParams.Aggregate.SUM);
|
||||
long bresult = jedis.zunionstore(SafeEncoder.encode("dst"), bparams,
|
||||
bfoo, bbar);
|
||||
@@ -810,8 +925,8 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
assertEquals(2, bresult);
|
||||
|
||||
Set<Tuple> bexpected = new LinkedHashSet<Tuple>();
|
||||
bexpected.add(new Tuple(bb, new Double(8)));
|
||||
bexpected.add(new Tuple(ba, new Double(6)));
|
||||
bexpected.add(new Tuple(bb, new Double(9)));
|
||||
bexpected.add(new Tuple(ba, new Double(7)));
|
||||
|
||||
assertEquals(bexpected,
|
||||
jedis.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100));
|
||||
@@ -855,14 +970,14 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.zadd("bar", 2, "a");
|
||||
|
||||
ZParams params = new ZParams();
|
||||
params.weights(2, 2);
|
||||
params.weights(2, 2.5);
|
||||
params.aggregate(ZParams.Aggregate.SUM);
|
||||
long result = jedis.zinterstore("dst", params, "foo", "bar");
|
||||
|
||||
assertEquals(1, result);
|
||||
|
||||
Set<Tuple> expected = new LinkedHashSet<Tuple>();
|
||||
expected.add(new Tuple("a", new Double(6)));
|
||||
expected.add(new Tuple("a", new Double(7)));
|
||||
|
||||
assertEquals(expected, jedis.zrangeWithScores("dst", 0, 100));
|
||||
|
||||
@@ -872,7 +987,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.zadd(bbar, 2, ba);
|
||||
|
||||
ZParams bparams = new ZParams();
|
||||
bparams.weights(2, 2);
|
||||
bparams.weights(2, 2.5);
|
||||
bparams.aggregate(ZParams.Aggregate.SUM);
|
||||
long bresult = jedis.zinterstore(SafeEncoder.encode("dst"), bparams,
|
||||
bfoo, bbar);
|
||||
@@ -880,7 +995,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
assertEquals(1, bresult);
|
||||
|
||||
Set<Tuple> bexpected = new LinkedHashSet<Tuple>();
|
||||
bexpected.add(new Tuple(ba, new Double(6)));
|
||||
bexpected.add(new Tuple(ba, new Double(7)));
|
||||
|
||||
assertEquals(bexpected,
|
||||
jedis.zrangeWithScores(SafeEncoder.encode("dst"), 0, 100));
|
||||
@@ -903,7 +1018,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
ScanResult<Tuple> result = jedis.zscan("foo", SCAN_POINTER_START);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
@@ -926,7 +1041,7 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
jedis.zadd("foo", 11, "aa");
|
||||
ScanResult<Tuple> result = jedis.zscan("foo", SCAN_POINTER_START, params);
|
||||
|
||||
assertEquals(SCAN_POINTER_START, result.getStringCursor());
|
||||
assertEquals(SCAN_POINTER_START, result.getCursor());
|
||||
assertFalse(result.getResult().isEmpty());
|
||||
|
||||
// binary
|
||||
@@ -970,4 +1085,4 @@ public class SortedSetCommandsTest extends JedisCommandTestBase {
|
||||
|
||||
assertFalse(bResult.getResult().isEmpty());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,7 +8,8 @@ import redis.clients.jedis.JedisPubSub;
|
||||
import redis.clients.jedis.tests.utils.FailoverAbortedException;
|
||||
|
||||
public class JedisSentinelTestUtil {
|
||||
public static HostAndPort waitForNewPromotedMaster(Jedis sentinelJedis)
|
||||
public static HostAndPort waitForNewPromotedMaster(final String masterName,
|
||||
final Jedis sentinelJedis, final Jedis commandJedis)
|
||||
throws InterruptedException {
|
||||
|
||||
final AtomicReference<String> newmaster = new AtomicReference<String>(
|
||||
@@ -47,6 +48,7 @@ public class JedisSentinelTestUtil {
|
||||
|
||||
@Override
|
||||
public void onPSubscribe(String pattern, int subscribedChannels) {
|
||||
commandJedis.sentinelFailover(masterName);
|
||||
}
|
||||
}, "*");
|
||||
|
||||
|
||||
Reference in New Issue
Block a user