Merge branch 'master' into pipeline-and-transaction-can-handle-responses-on-their-own-status

* it's broken with later features, resetState()
* fixed resetState() to make it work with this PR

Conflicts:
	src/main/java/redis/clients/jedis/BinaryJedis.java
	src/main/java/redis/clients/jedis/Connection.java
	src/main/java/redis/clients/jedis/Pipeline.java
	src/main/java/redis/clients/jedis/Transaction.java
	src/main/java/redis/clients/jedis/TransactionBlock.java
This commit is contained in:
Jungtaek Lim
2014-08-08 10:46:43 +09:00
124 changed files with 9710 additions and 6367 deletions

3
.gitignore vendored
View File

@@ -9,3 +9,6 @@ target/
build/ build/
bin/ bin/
tags tags
.idea
*.aof
*.rdb

7
.travis.yml Normal file
View File

@@ -0,0 +1,7 @@
language: java
jdk:
- openjdk6
- openjdk7
- oraclejdk7
install: make travis-install
script: make test

116
Makefile
View File

@@ -1,3 +1,5 @@
PATH := ./redis-git/src:${PATH}
define REDIS1_CONF define REDIS1_CONF
daemonize yes daemonize yes
port 6379 port 6379
@@ -23,6 +25,7 @@ define REDIS3_CONF
daemonize yes daemonize yes
port 6381 port 6381
requirepass foobared requirepass foobared
masterauth foobared
pidfile /tmp/redis3.pid pidfile /tmp/redis3.pid
logfile /tmp/redis3.log logfile /tmp/redis3.log
save "" save ""
@@ -50,7 +53,7 @@ pidfile /tmp/redis5.pid
logfile /tmp/redis5.log logfile /tmp/redis5.log
save "" save ""
appendonly no appendonly no
slaveof localhost 6381 slaveof localhost 6379
endef endef
define REDIS6_CONF define REDIS6_CONF
@@ -62,7 +65,18 @@ pidfile /tmp/redis6.pid
logfile /tmp/redis6.log logfile /tmp/redis6.log
save "" save ""
appendonly no appendonly no
slaveof localhost 6379 endef
define REDIS7_CONF
daemonize yes
port 6385
requirepass foobared
masterauth foobared
pidfile /tmp/redis7.pid
logfile /tmp/redis7.log
save ""
appendonly no
slaveof localhost 6384
endef endef
# SENTINELS # SENTINELS
@@ -71,8 +85,8 @@ port 26379
daemonize yes daemonize yes
sentinel monitor mymaster 127.0.0.1 6379 1 sentinel monitor mymaster 127.0.0.1 6379 1
sentinel auth-pass mymaster foobared sentinel auth-pass mymaster foobared
sentinel down-after-milliseconds mymaster 3000 sentinel down-after-milliseconds mymaster 2000
sentinel failover-timeout mymaster 900000 sentinel failover-timeout mymaster 120000
sentinel parallel-syncs mymaster 1 sentinel parallel-syncs mymaster 1
pidfile /tmp/sentinel1.pid pidfile /tmp/sentinel1.pid
logfile /tmp/sentinel1.log logfile /tmp/sentinel1.log
@@ -81,11 +95,11 @@ endef
define REDIS_SENTINEL2 define REDIS_SENTINEL2
port 26380 port 26380
daemonize yes daemonize yes
sentinel monitor mymaster 127.0.0.1 6381 2 sentinel monitor mymaster 127.0.0.1 6381 1
sentinel auth-pass mymaster foobared sentinel auth-pass mymaster foobared
sentinel down-after-milliseconds mymaster 3000 sentinel down-after-milliseconds mymaster 2000
sentinel parallel-syncs mymaster 1 sentinel parallel-syncs mymaster 1
sentinel failover-timeout mymaster 900000 sentinel failover-timeout mymaster 120000
pidfile /tmp/sentinel2.pid pidfile /tmp/sentinel2.pid
logfile /tmp/sentinel2.log logfile /tmp/sentinel2.log
endef endef
@@ -93,11 +107,11 @@ endef
define REDIS_SENTINEL3 define REDIS_SENTINEL3
port 26381 port 26381
daemonize yes daemonize yes
sentinel monitor mymaster 127.0.0.1 6381 2 sentinel monitor mymasterfailover 127.0.0.1 6384 1
sentinel auth-pass mymaster foobared sentinel auth-pass mymasterfailover foobared
sentinel down-after-milliseconds mymaster 3000 sentinel down-after-milliseconds mymasterfailover 2000
sentinel parallel-syncs mymaster 1 sentinel failover-timeout mymasterfailover 120000
sentinel failover-timeout mymaster 900000 sentinel parallel-syncs mymasterfailover 1
pidfile /tmp/sentinel3.pid pidfile /tmp/sentinel3.pid
logfile /tmp/sentinel3.log logfile /tmp/sentinel3.log
endef endef
@@ -106,6 +120,7 @@ endef
define REDIS_CLUSTER_NODE1_CONF define REDIS_CLUSTER_NODE1_CONF
daemonize yes daemonize yes
port 7379 port 7379
cluster-node-timeout 50
pidfile /tmp/redis_cluster_node1.pid pidfile /tmp/redis_cluster_node1.pid
logfile /tmp/redis_cluster_node1.log logfile /tmp/redis_cluster_node1.log
save "" save ""
@@ -117,6 +132,7 @@ endef
define REDIS_CLUSTER_NODE2_CONF define REDIS_CLUSTER_NODE2_CONF
daemonize yes daemonize yes
port 7380 port 7380
cluster-node-timeout 50
pidfile /tmp/redis_cluster_node2.pid pidfile /tmp/redis_cluster_node2.pid
logfile /tmp/redis_cluster_node2.log logfile /tmp/redis_cluster_node2.log
save "" save ""
@@ -128,6 +144,7 @@ endef
define REDIS_CLUSTER_NODE3_CONF define REDIS_CLUSTER_NODE3_CONF
daemonize yes daemonize yes
port 7381 port 7381
cluster-node-timeout 50
pidfile /tmp/redis_cluster_node3.pid pidfile /tmp/redis_cluster_node3.pid
logfile /tmp/redis_cluster_node3.log logfile /tmp/redis_cluster_node3.log
save "" save ""
@@ -136,18 +153,58 @@ cluster-enabled yes
cluster-config-file /tmp/redis_cluster_node3.conf cluster-config-file /tmp/redis_cluster_node3.conf
endef endef
define REDIS_CLUSTER_NODE4_CONF
daemonize yes
port 7382
cluster-node-timeout 50
pidfile /tmp/redis_cluster_node4.pid
logfile /tmp/redis_cluster_node4.log
save ""
appendonly no
cluster-enabled yes
cluster-config-file /tmp/redis_cluster_node4.conf
endef
define REDIS_CLUSTER_NODE5_CONF
daemonize yes
port 7383
cluster-node-timeout 5000
pidfile /tmp/redis_cluster_node5.pid
logfile /tmp/redis_cluster_node5.log
save ""
appendonly no
cluster-enabled yes
cluster-config-file /tmp/redis_cluster_node5.conf
endef
define REDIS_CLUSTER_NODE6_CONF
daemonize yes
port 7384
cluster-node-timeout 5000
pidfile /tmp/redis_cluster_node6.pid
logfile /tmp/redis_cluster_node6.log
save ""
appendonly no
cluster-enabled yes
cluster-config-file /tmp/redis_cluster_node6.conf
endef
export REDIS1_CONF export REDIS1_CONF
export REDIS2_CONF export REDIS2_CONF
export REDIS3_CONF export REDIS3_CONF
export REDIS4_CONF export REDIS4_CONF
export REDIS5_CONF export REDIS5_CONF
export REDIS6_CONF export REDIS6_CONF
export REDIS7_CONF
export REDIS_SENTINEL1 export REDIS_SENTINEL1
export REDIS_SENTINEL2 export REDIS_SENTINEL2
export REDIS_SENTINEL3 export REDIS_SENTINEL3
export REDIS_CLUSTER_NODE1_CONF export REDIS_CLUSTER_NODE1_CONF
export REDIS_CLUSTER_NODE2_CONF export REDIS_CLUSTER_NODE2_CONF
export REDIS_CLUSTER_NODE3_CONF export REDIS_CLUSTER_NODE3_CONF
export REDIS_CLUSTER_NODE4_CONF
export REDIS_CLUSTER_NODE5_CONF
export REDIS_CLUSTER_NODE6_CONF
start: cleanup start: cleanup
echo "$$REDIS1_CONF" | redis-server - echo "$$REDIS1_CONF" | redis-server -
@@ -156,6 +213,7 @@ start: cleanup
echo "$$REDIS4_CONF" | redis-server - echo "$$REDIS4_CONF" | redis-server -
echo "$$REDIS5_CONF" | redis-server - echo "$$REDIS5_CONF" | redis-server -
echo "$$REDIS6_CONF" | redis-server - echo "$$REDIS6_CONF" | redis-server -
echo "$$REDIS7_CONF" | redis-server -
echo "$$REDIS_SENTINEL1" > /tmp/sentinel1.conf && redis-server /tmp/sentinel1.conf --sentinel echo "$$REDIS_SENTINEL1" > /tmp/sentinel1.conf && redis-server /tmp/sentinel1.conf --sentinel
@sleep 0.5 @sleep 0.5
echo "$$REDIS_SENTINEL2" > /tmp/sentinel2.conf && redis-server /tmp/sentinel2.conf --sentinel echo "$$REDIS_SENTINEL2" > /tmp/sentinel2.conf && redis-server /tmp/sentinel2.conf --sentinel
@@ -164,27 +222,40 @@ start: cleanup
echo "$$REDIS_CLUSTER_NODE1_CONF" | redis-server - echo "$$REDIS_CLUSTER_NODE1_CONF" | redis-server -
echo "$$REDIS_CLUSTER_NODE2_CONF" | redis-server - echo "$$REDIS_CLUSTER_NODE2_CONF" | redis-server -
echo "$$REDIS_CLUSTER_NODE3_CONF" | redis-server - echo "$$REDIS_CLUSTER_NODE3_CONF" | redis-server -
echo "$$REDIS_CLUSTER_NODE4_CONF" | redis-server -
echo "$$REDIS_CLUSTER_NODE5_CONF" | redis-server -
echo "$$REDIS_CLUSTER_NODE6_CONF" | redis-server -
cleanup: cleanup:
rm -vf /tmp/redis_cluster_node*.conf - rm -vf /tmp/redis_cluster_node*.conf 2>/dev/null
- rm dump.rdb appendonly.aof - 2>/dev/null
stop: stop:
kill `cat /tmp/redis1.pid` kill `cat /tmp/redis1.pid`
kill `cat /tmp/redis2.pid` kill `cat /tmp/redis2.pid`
# this get's segfaulted by the tests kill `cat /tmp/redis3.pid`
kill `cat /tmp/redis3.pid` || true kill `cat /tmp/redis4.pid`
kill `cat /tmp/redis4.pid` || true kill `cat /tmp/redis5.pid`
kill `cat /tmp/redis5.pid` || true kill `cat /tmp/redis6.pid`
kill `cat /tmp/redis6.pid` || true kill `cat /tmp/redis7.pid`
kill `cat /tmp/sentinel1.pid` kill `cat /tmp/sentinel1.pid`
kill `cat /tmp/sentinel2.pid` kill `cat /tmp/sentinel2.pid`
kill `cat /tmp/sentinel3.pid` kill `cat /tmp/sentinel3.pid`
kill `cat /tmp/redis_cluster_node1.pid` || true kill `cat /tmp/redis_cluster_node1.pid` || true
kill `cat /tmp/redis_cluster_node2.pid` || true kill `cat /tmp/redis_cluster_node2.pid` || true
kill `cat /tmp/redis_cluster_node3.pid` || true kill `cat /tmp/redis_cluster_node3.pid` || true
kill `cat /tmp/redis_cluster_node4.pid` || true
kill `cat /tmp/redis_cluster_node5.pid` || true
kill `cat /tmp/redis_cluster_node6.pid` || true
rm -f /tmp/sentinel1.conf
rm -f /tmp/sentinel2.conf
rm -f /tmp/sentinel3.conf
rm -f /tmp/redis_cluster_node1.conf rm -f /tmp/redis_cluster_node1.conf
rm -f /tmp/redis_cluster_node2.conf rm -f /tmp/redis_cluster_node2.conf
rm -f /tmp/redis_cluster_node3.conf rm -f /tmp/redis_cluster_node3.conf
rm -f /tmp/redis_cluster_node4.conf
rm -f /tmp/redis_cluster_node5.conf
rm -f /tmp/redis_cluster_node6.conf
test: test:
make start make start
@@ -192,6 +263,11 @@ test:
mvn -Dtest=${TEST} clean compile test mvn -Dtest=${TEST} clean compile test
make stop make stop
package:
make start
mvn clean package
make stop
deploy: deploy:
make start make start
mvn clean deploy mvn clean deploy
@@ -204,4 +280,8 @@ release:
mvn release:perform mvn release:perform
make stop make stop
travis-install:
[ ! -e redis-git ] && git clone https://github.com/antirez/redis.git redis-git || true
make -C redis-git -j4
.PHONY: test .PHONY: test

View File

@@ -1,10 +1,12 @@
[![Build Status](https://travis-ci.org/xetorthio/jedis.png?branch=master)](https://travis-ci.org/xetorthio/jedis)
# Jedis # Jedis
Jedis is a blazingly small and sane [Redis](http://github.com/antirez/redis "Redis") java client. Jedis is a blazingly small and sane [Redis](http://github.com/antirez/redis "Redis") java client.
Jedis was conceived to be EASY to use. Jedis was conceived to be EASY to use.
Jedis is fully compatible with redis 2.6.14. Jedis is fully compatible with redis 2.8.5.
## Community ## Community
@@ -38,7 +40,7 @@ All of the following redis features are supported:
## How do I use it? ## How do I use it?
You can download the latest build at: You can download the latest build at:
http://github.com/xetorthio/jedis/downloads http://github.com/xetorthio/jedis/releases
Or use it as a maven dependency: Or use it as a maven dependency:
@@ -46,7 +48,7 @@ Or use it as a maven dependency:
<dependency> <dependency>
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>
<version>2.2.1</version> <version>2.4.2</version>
<type>jar</type> <type>jar</type>
<scope>compile</scope> <scope>compile</scope>
</dependency> </dependency>
@@ -73,8 +75,8 @@ Redis cluster [specification](http://redis.io/topics/cluster-spec) (still under
```java ```java
Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>(); Set<HostAndPort> jedisClusterNodes = new HashSet<HostAndPort>();
//Jedis Cluster will attempt to discover cluster nodes automatically //Jedis Cluster will attempt to discover cluster nodes automatically
jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379)); jedisClusterNodes.add(new HostAndPort("127.0.0.1", 7379));
JedisCluster jc = new JedisCluster(jedisClusterNode); JedisCluster jc = new JedisCluster(jedisClusterNodes);
jc.set("foo", "bar"); jc.set("foo", "bar");
String value = jc.get("foo"); String value = jc.get("foo");
``` ```

View File

@@ -3,7 +3,7 @@ apply plugin: 'maven'
apply plugin: 'eclipse' apply plugin: 'eclipse'
group = 'com.googlecode.jedis' group = 'com.googlecode.jedis'
archiveBaseName = 'jedis' archivesBaseName = 'jedis'
version = '1.5.0' version = '1.5.0'
repositories { repositories {

View File

@@ -9,7 +9,7 @@
<packaging>jar</packaging> <packaging>jar</packaging>
<groupId>redis.clients</groupId> <groupId>redis.clients</groupId>
<artifactId>jedis</artifactId> <artifactId>jedis</artifactId>
<version>2.2.2-SNAPSHOT</version> <version>2.5.2-SNAPSHOT</version>
<name>Jedis</name> <name>Jedis</name>
<description>Jedis is a blazingly small and sane Redis java client.</description> <description>Jedis is a blazingly small and sane Redis java client.</description>
<url>https://github.com/xetorthio/jedis</url> <url>https://github.com/xetorthio/jedis</url>
@@ -45,9 +45,9 @@
</scm> </scm>
<properties> <properties>
<redis-hosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383,localhost:6384</redis-hosts> <redis-hosts>localhost:6379,localhost:6380,localhost:6381,localhost:6382,localhost:6383,localhost:6384,localhost:6385</redis-hosts>
<sentinel-hosts>localhost:26379,localhost:26380,localhost:26381</sentinel-hosts> <sentinel-hosts>localhost:26379,localhost:26380,localhost:26381</sentinel-hosts>
<cluster-hosts>localhost:7379,localhost:7380,localhost:7381</cluster-hosts> <cluster-hosts>localhost:7379,localhost:7380,localhost:7381,localhost:7382,localhost:7383,localhost:7384,localhost:7385</cluster-hosts>
<github.global.server>github</github.global.server> <github.global.server>github</github.global.server>
</properties> </properties>

View File

@@ -1,6 +1,5 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
public interface AdvancedBinaryJedisCommands { public interface AdvancedBinaryJedisCommands {

View File

@@ -1,9 +1,8 @@
package redis.clients.jedis; package redis.clients.jedis;
import redis.clients.util.Slowlog;
import java.util.List; import java.util.List;
import redis.clients.util.Slowlog;
public interface AdvancedJedisCommands { public interface AdvancedJedisCommands {
List<String> configGet(String pattern); List<String> configGet(String pattern);

View File

@@ -1,5 +1,6 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List;
/** /**
* Pipelined responses for all of the low level, non key related commands * Pipelined responses for all of the low level, non key related commands
@@ -26,6 +27,8 @@ public interface BasicRedisPipeline {
Response<String> info(); Response<String> info();
Response<List<String>> time();
Response<Long> dbSize(); Response<Long> dbSize();
Response<String> shutdown(); Response<String> shutdown();

View File

@@ -34,10 +34,16 @@ public class BinaryClient extends Connection {
private long db; private long db;
private boolean isInWatch;
public boolean isInMulti() { public boolean isInMulti() {
return isInMulti; return isInMulti;
} }
public boolean isInWatch() {
return isInWatch;
}
public BinaryClient(final String host) { public BinaryClient(final String host) {
super(host); super(host);
} }
@@ -82,11 +88,11 @@ public class BinaryClient extends Connection {
sendCommand(Command.SET, key, value); sendCommand(Command.SET, key, value);
} }
public void set(final byte[] key, final byte[] value, final byte[] nxxx, final byte[] expx, final long time) { public void set(final byte[] key, final byte[] value, final byte[] nxxx,
sendCommand(Command.SET, key, value, nxxx, expx, toByteArray(time)); final byte[] expx, final long time) {
sendCommand(Command.SET, key, value, nxxx, expx, toByteArray(time));
} }
public void get(final byte[] key) { public void get(final byte[] key) {
sendCommand(Command.GET, key); sendCommand(Command.GET, key);
} }
@@ -193,6 +199,10 @@ public class BinaryClient extends Connection {
sendCommand(INCRBY, key, toByteArray(integer)); sendCommand(INCRBY, key, toByteArray(integer));
} }
public void incrByFloat(final byte[] key, final double value) {
sendCommand(INCRBYFLOAT, key, toByteArray(value));
}
public void incr(final byte[] key) { public void incr(final byte[] key) {
sendCommand(INCR, key); sendCommand(INCR, key);
} }
@@ -377,15 +387,16 @@ public class BinaryClient extends Connection {
sendCommand(ZADD, key, toByteArray(score), member); sendCommand(ZADD, key, toByteArray(score), member);
} }
public void zaddBinary(final byte[] key, Map<Double, byte[]> scoreMembers) { public void zaddBinary(final byte[] key,
final Map<byte[], Double> scoreMembers) {
ArrayList<byte[]> args = new ArrayList<byte[]>( ArrayList<byte[]> args = new ArrayList<byte[]>(
scoreMembers.size() * 2 + 1); scoreMembers.size() * 2 + 1);
args.add(key); args.add(key);
for (Map.Entry<Double, byte[]> entry : scoreMembers.entrySet()) { for (Map.Entry<byte[], Double> entry : scoreMembers.entrySet()) {
args.add(toByteArray(entry.getKey())); args.add(toByteArray(entry.getValue()));
args.add(entry.getValue()); args.add(entry.getKey());
} }
byte[][] argsArray = new byte[args.size()][]; byte[][] argsArray = new byte[args.size()][];
@@ -447,19 +458,23 @@ public class BinaryClient extends Connection {
public void discard() { public void discard() {
sendCommand(DISCARD); sendCommand(DISCARD);
isInMulti = false; isInMulti = false;
isInWatch = false;
} }
public void exec() { public void exec() {
sendCommand(EXEC); sendCommand(EXEC);
isInMulti = false; isInMulti = false;
isInWatch = false;
} }
public void watch(final byte[]... keys) { public void watch(final byte[]... keys) {
sendCommand(WATCH, keys); sendCommand(WATCH, keys);
isInWatch = true;
} }
public void unwatch() { public void unwatch() {
sendCommand(UNWATCH); sendCommand(UNWATCH);
isInWatch = false;
} }
public void sort(final byte[] key) { public void sort(final byte[] key) {
@@ -478,12 +493,12 @@ public class BinaryClient extends Connection {
} }
public void blpop(final int timeout, final byte[]... keys) { public void blpop(final int timeout, final byte[]... keys) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
for (final byte[] arg : keys) { for (final byte[] arg : keys) {
args.add(arg); args.add(arg);
} }
args.add(Protocol.toByteArray(timeout)); args.add(Protocol.toByteArray(timeout));
blpop(args.toArray(new byte[args.size()][])); blpop(args.toArray(new byte[args.size()][]));
} }
public void sort(final byte[] key, final SortingParams sortingParameters, public void sort(final byte[] key, final SortingParams sortingParameters,
@@ -505,12 +520,12 @@ public class BinaryClient extends Connection {
} }
public void brpop(final int timeout, final byte[]... keys) { public void brpop(final int timeout, final byte[]... keys) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
for (final byte[] arg : keys) { for (final byte[] arg : keys) {
args.add(arg); args.add(arg);
} }
args.add(Protocol.toByteArray(timeout)); args.add(Protocol.toByteArray(timeout));
brpop(args.toArray(new byte[args.size()][])); brpop(args.toArray(new byte[args.size()][]));
} }
public void auth(final String password) { public void auth(final String password) {
@@ -543,32 +558,39 @@ public class BinaryClient extends Connection {
} }
public void punsubscribe(final byte[]... patterns) { public void punsubscribe(final byte[]... patterns) {
sendCommand(PUNSUBSCRIBE, patterns); sendCommand(PUNSUBSCRIBE, patterns);
} }
public void pubsub(final byte[]... args) {
sendCommand(PUBSUB, args);
}
public void zcount(final byte[] key, final double min, final double max) { public void zcount(final byte[] key, final double min, final double max) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZCOUNT, key, byteArrayMin, byteArrayMax); sendCommand(ZCOUNT, key, byteArrayMin, byteArrayMax);
} }
public void zcount(final byte[] key, final byte min[], final byte max[]) { public void zcount(final byte[] key, final byte min[], final byte max[]) {
sendCommand(ZCOUNT, key, min, max); sendCommand(ZCOUNT, key, min, max);
} }
public void zcount(final byte[] key, final String min, final String max) { public void zcount(final byte[] key, final String min, final String max) {
sendCommand(ZCOUNT, key, min.getBytes(), max.getBytes()); sendCommand(ZCOUNT, key, min.getBytes(), max.getBytes());
} }
public void zrangeByScore(final byte[] key, final double min, public void zrangeByScore(final byte[] key, final double min,
final double max) { final double max) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax); sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax);
} }
public void zrangeByScore(final byte[] key, final byte[] min, public void zrangeByScore(final byte[] key, final byte[] min,
@@ -577,17 +599,19 @@ public class BinaryClient extends Connection {
} }
public void zrangeByScore(final byte[] key, final String min, public void zrangeByScore(final byte[] key, final String min,
final String max) { final String max) {
sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes()); sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes());
} }
public void zrevrangeByScore(final byte[] key, final double max, public void zrevrangeByScore(final byte[] key, final double max,
final double min) { final double min) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin); sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin);
} }
public void zrevrangeByScore(final byte[] key, final byte[] max, public void zrevrangeByScore(final byte[] key, final byte[] max,
@@ -596,112 +620,123 @@ public class BinaryClient extends Connection {
} }
public void zrevrangeByScore(final byte[] key, final String max, public void zrevrangeByScore(final byte[] key, final String max,
final String min) { final String min) {
sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes()); sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes());
} }
public void zrangeByScore(final byte[] key, final double min, public void zrangeByScore(final byte[] key, final double min,
final double max, final int offset, int count) { final double max, final int offset, int count) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, LIMIT.raw,
LIMIT.raw, toByteArray(offset), toByteArray(count)); toByteArray(offset), toByteArray(count));
} }
public void zrangeByScore(final byte[] key, final String min, public void zrangeByScore(final byte[] key, final String min,
final String max, final int offset, int count) { final String max, final int offset, int count) {
sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(),
LIMIT.raw, toByteArray(offset), toByteArray(count)); LIMIT.raw, toByteArray(offset), toByteArray(count));
} }
public void zrevrangeByScore(final byte[] key, final double max, public void zrevrangeByScore(final byte[] key, final double max,
final double min, final int offset, int count) { final double min, final int offset, int count) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin,
LIMIT.raw, toByteArray(offset), toByteArray(count)); LIMIT.raw, toByteArray(offset), toByteArray(count));
} }
public void zrevrangeByScore(final byte[] key, final String max, public void zrevrangeByScore(final byte[] key, final String max,
final String min, final int offset, int count) { final String min, final int offset, int count) {
sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(),
LIMIT.raw, toByteArray(offset), toByteArray(count)); LIMIT.raw, toByteArray(offset), toByteArray(count));
} }
public void zrangeByScoreWithScores(final byte[] key, final double min, public void zrangeByScoreWithScores(final byte[] key, final double min,
final double max) { final double max) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax,
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrangeByScoreWithScores(final byte[] key, final String min, public void zrangeByScoreWithScores(final byte[] key, final String min,
final String max) { final String max) {
sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(),
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrevrangeByScoreWithScores(final byte[] key, final double max, public void zrevrangeByScoreWithScores(final byte[] key, final double max,
final double min) { final double min) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin,
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrevrangeByScoreWithScores(final byte[] key, final String max, public void zrevrangeByScoreWithScores(final byte[] key, final String max,
final String min) { final String min) {
sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(),
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrangeByScoreWithScores(final byte[] key, final double min, public void zrangeByScoreWithScores(final byte[] key, final double min,
final double max, final int offset, final int count) { final double max, final int offset, final int count) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, sendCommand(ZRANGEBYSCORE, key, byteArrayMin, byteArrayMax, LIMIT.raw,
LIMIT.raw, toByteArray(offset), toByteArray(count), toByteArray(offset), toByteArray(count), WITHSCORES.raw);
WITHSCORES.raw);
} }
public void zrangeByScoreWithScores(final byte[] key, final String min, public void zrangeByScoreWithScores(final byte[] key, final String min,
final String max, final int offset, final int count) { final String max, final int offset, final int count) {
sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(), sendCommand(ZRANGEBYSCORE, key, min.getBytes(), max.getBytes(),
LIMIT.raw, toByteArray(offset), toByteArray(count), LIMIT.raw, toByteArray(offset), toByteArray(count),
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrevrangeByScoreWithScores(final byte[] key, final double max, public void zrevrangeByScoreWithScores(final byte[] key, final double max,
final double min, final int offset, final int count) { final double min, final int offset, final int count) {
byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf".getBytes() : toByteArray(min); byte byteArrayMin[] = (min == Double.NEGATIVE_INFINITY) ? "-inf"
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf".getBytes() : toByteArray(max); .getBytes() : toByteArray(min);
byte byteArrayMax[] = (max == Double.POSITIVE_INFINITY) ? "+inf"
.getBytes() : toByteArray(max);
sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin, sendCommand(ZREVRANGEBYSCORE, key, byteArrayMax, byteArrayMin,
LIMIT.raw, toByteArray(offset), toByteArray(count), LIMIT.raw, toByteArray(offset), toByteArray(count),
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrevrangeByScoreWithScores(final byte[] key, final String max, public void zrevrangeByScoreWithScores(final byte[] key, final String max,
final String min, final int offset, final int count) { final String min, final int offset, final int count) {
sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(), sendCommand(ZREVRANGEBYSCORE, key, max.getBytes(), min.getBytes(),
LIMIT.raw, toByteArray(offset), toByteArray(count), LIMIT.raw, toByteArray(offset), toByteArray(count),
WITHSCORES.raw); WITHSCORES.raw);
} }
public void zrangeByScore(final byte[] key, final byte[] min, public void zrangeByScore(final byte[] key, final byte[] min,
@@ -749,8 +784,8 @@ public class BinaryClient extends Connection {
} }
public void zremrangeByScore(final byte[] key, final String start, public void zremrangeByScore(final byte[] key, final String start,
final String end) { final String end) {
sendCommand(ZREMRANGEBYSCORE, key, start.getBytes(), end.getBytes()); sendCommand(ZREMRANGEBYSCORE, key, start.getBytes(), end.getBytes());
} }
public void zunionstore(final byte[] dstkey, final byte[]... sets) { public void zunionstore(final byte[] dstkey, final byte[]... sets) {
@@ -888,13 +923,21 @@ public class BinaryClient extends Connection {
} }
public void setbit(byte[] key, long offset, boolean value) { public void setbit(byte[] key, long offset, boolean value) {
sendCommand(SETBIT, key, toByteArray(offset), toByteArray(value)); sendCommand(SETBIT, key, toByteArray(offset), toByteArray(value));
} }
public void getbit(byte[] key, long offset) { public void getbit(byte[] key, long offset) {
sendCommand(GETBIT, key, toByteArray(offset)); sendCommand(GETBIT, key, toByteArray(offset));
} }
public void bitpos(final byte[] key, final boolean value, final BitPosParams params) {
final List<byte[]> args = new ArrayList<byte[]>();
args.add(key);
args.add(toByteArray(value));
args.addAll(params.getParams());
sendCommand(BITPOS, args.toArray(new byte[args.size()][]));
}
public void setrange(byte[] key, long offset, byte[] value) { public void setrange(byte[] key, long offset, byte[] value) {
sendCommand(SETRANGE, key, toByteArray(offset), value); sendCommand(SETRANGE, key, toByteArray(offset), value);
} }
@@ -913,6 +956,17 @@ public class BinaryClient extends Connection {
super.disconnect(); super.disconnect();
} }
@Override
public void close() {
db = 0;
super.close();
}
public void resetState() {
if (isInWatch())
unwatch();
}
private void sendEvalCommand(Command command, byte[] script, private void sendEvalCommand(Command command, byte[] script,
byte[] keyCount, byte[][] params) { byte[] keyCount, byte[][] params) {
@@ -932,7 +986,7 @@ public class BinaryClient extends Connection {
} }
public void eval(byte[] script, int keyCount, byte[]... params) { public void eval(byte[] script, int keyCount, byte[]... params) {
eval(script, toByteArray(keyCount), params); eval(script, toByteArray(keyCount), params);
} }
public void evalsha(byte[] sha1, byte[] keyCount, byte[]... params) { public void evalsha(byte[] sha1, byte[] keyCount, byte[]... params) {
@@ -940,7 +994,7 @@ public class BinaryClient extends Connection {
} }
public void evalsha(byte[] sha1, int keyCount, byte[]... params) { public void evalsha(byte[] sha1, int keyCount, byte[]... params) {
sendEvalCommand(EVALSHA, sha1, toByteArray(keyCount), params); sendEvalCommand(EVALSHA, sha1, toByteArray(keyCount), params);
} }
public void scriptFlush() { public void scriptFlush() {
@@ -993,114 +1047,127 @@ public class BinaryClient extends Connection {
} }
public void bitcount(byte[] key) { public void bitcount(byte[] key) {
sendCommand(BITCOUNT, key); sendCommand(BITCOUNT, key);
} }
public void bitcount(byte[] key, long start, long end) { public void bitcount(byte[] key, long start, long end) {
sendCommand(BITCOUNT, key, toByteArray(start), toByteArray(end)); sendCommand(BITCOUNT, key, toByteArray(start), toByteArray(end));
} }
public void bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { public void bitop(BitOP op, byte[] destKey, byte[]... srcKeys) {
Keyword kw = Keyword.AND; Keyword kw = Keyword.AND;
int len = srcKeys.length; int len = srcKeys.length;
switch (op) { switch (op) {
case AND: case AND:
kw = Keyword.AND; kw = Keyword.AND;
break; break;
case OR: case OR:
kw = Keyword.OR; kw = Keyword.OR;
break; break;
case XOR: case XOR:
kw = Keyword.XOR; kw = Keyword.XOR;
break; break;
case NOT: case NOT:
kw = Keyword.NOT; kw = Keyword.NOT;
len = Math.min(1, len); len = Math.min(1, len);
break; break;
} }
byte[][] bargs = new byte[len + 2][]; byte[][] bargs = new byte[len + 2][];
bargs[0] = kw.raw; bargs[0] = kw.raw;
bargs[1] = destKey; bargs[1] = destKey;
for (int i = 0; i < len; ++i) { for (int i = 0; i < len; ++i) {
bargs[i + 2] = srcKeys[i]; bargs[i + 2] = srcKeys[i];
} }
sendCommand(BITOP, bargs); sendCommand(BITOP, bargs);
} }
public void sentinel(final byte[]... args) { public void sentinel(final byte[]... args) {
sendCommand(SENTINEL, args); sendCommand(SENTINEL, args);
} }
public void dump(final byte[] key) { public void dump(final byte[] key) {
sendCommand(DUMP, key); sendCommand(DUMP, key);
} }
public void restore(final byte[] key, final int ttl, final byte[] serializedValue) { public void restore(final byte[] key, final int ttl,
sendCommand(RESTORE, key, toByteArray(ttl), serializedValue); final byte[] serializedValue) {
sendCommand(RESTORE, key, toByteArray(ttl), serializedValue);
} }
@Deprecated
public void pexpire(final byte[] key, final int milliseconds) { public void pexpire(final byte[] key, final int milliseconds) {
sendCommand(PEXPIRE, key, toByteArray(milliseconds)); pexpire(key, (long) milliseconds);
}
public void pexpire(final byte[] key, final long milliseconds) {
sendCommand(PEXPIRE, key, toByteArray(milliseconds));
} }
public void pexpireAt(final byte[] key, final long millisecondsTimestamp) { public void pexpireAt(final byte[] key, final long millisecondsTimestamp) {
sendCommand(PEXPIREAT, key, toByteArray(millisecondsTimestamp)); sendCommand(PEXPIREAT, key, toByteArray(millisecondsTimestamp));
} }
public void pttl(final byte[] key) { public void pttl(final byte[] key) {
sendCommand(PTTL, key); sendCommand(PTTL, key);
} }
public void incrByFloat(final byte[] key, final double increment) { public void psetex(final byte[] key, final int milliseconds,
sendCommand(INCRBYFLOAT, key, toByteArray(increment)); final byte[] value) {
} sendCommand(PSETEX, key, toByteArray(milliseconds), value);
public void psetex(final byte[] key, final int milliseconds, final byte[] value) {
sendCommand(PSETEX, key, toByteArray(milliseconds), value);
} }
public void set(final byte[] key, final byte[] value, final byte[] nxxx) { public void set(final byte[] key, final byte[] value, final byte[] nxxx) {
sendCommand(Command.SET, key, value, nxxx); sendCommand(Command.SET, key, value, nxxx);
} }
public void set(final byte[] key, final byte[] value, final byte[] nxxx, final byte[] expx, final int time) { public void set(final byte[] key, final byte[] value, final byte[] nxxx,
sendCommand(Command.SET, key, value, nxxx, expx, toByteArray(time)); final byte[] expx, final int time) {
sendCommand(Command.SET, key, value, nxxx, expx, toByteArray(time));
} }
public void srandmember(final byte[] key, final int count) { public void srandmember(final byte[] key, final int count) {
sendCommand(SRANDMEMBER, key, toByteArray(count)); sendCommand(SRANDMEMBER, key, toByteArray(count));
} }
public void clientKill(final byte[] client) { public void clientKill(final byte[] client) {
sendCommand(CLIENT, Keyword.KILL.raw, client); sendCommand(CLIENT, Keyword.KILL.raw, client);
} }
public void clientGetname() { public void clientGetname() {
sendCommand(CLIENT, Keyword.GETNAME.raw); sendCommand(CLIENT, Keyword.GETNAME.raw);
} }
public void clientList() { public void clientList() {
sendCommand(CLIENT, Keyword.LIST.raw); sendCommand(CLIENT, Keyword.LIST.raw);
} }
public void clientSetname(final byte[] name) { public void clientSetname(final byte[] name) {
sendCommand(CLIENT, Keyword.SETNAME.raw, name); sendCommand(CLIENT, Keyword.SETNAME.raw, name);
} }
public void time() { public void time() {
sendCommand(TIME); sendCommand(TIME);
} }
public void migrate(final byte[] host, final int port, final byte[] key, final int destinationDb, final int timeout) { public void migrate(final byte[] host, final int port, final byte[] key,
sendCommand(MIGRATE, host, toByteArray(port), key, toByteArray(destinationDb), toByteArray(timeout)); final int destinationDb, final int timeout) {
sendCommand(MIGRATE, host, toByteArray(port), key,
toByteArray(destinationDb), toByteArray(timeout));
} }
public void hincrByFloat(final byte[] key, final byte[] field, double increment) { public void hincrByFloat(final byte[] key, final byte[] field,
sendCommand(HINCRBYFLOAT, key, field, toByteArray(increment)); double increment) {
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) { public void scan(int cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
args.add(toByteArray(cursor)); args.add(toByteArray(cursor));
@@ -1108,28 +1175,77 @@ public class BinaryClient extends Connection {
sendCommand(SCAN, args.toArray(new byte[args.size()][])); 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) { public void hscan(final byte[] key, int cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
args.add(key); args.add(key);
args.add(toByteArray(cursor)); args.add(toByteArray(cursor));
args.addAll(params.getParams()); args.addAll(params.getParams());
sendCommand(HSCAN, args.toArray(new byte[args.size()][])); 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) { public void sscan(final byte[] key, int cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
args.add(key); args.add(key);
args.add(toByteArray(cursor)); args.add(toByteArray(cursor));
args.addAll(params.getParams()); args.addAll(params.getParams());
sendCommand(SSCAN, args.toArray(new byte[args.size()][])); 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) { public void zscan(final byte[] key, int cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>(); final List<byte[]> args = new ArrayList<byte[]>();
args.add(key); args.add(key);
args.add(toByteArray(cursor)); args.add(toByteArray(cursor));
args.addAll(params.getParams()); args.addAll(params.getParams());
sendCommand(ZSCAN, args.toArray(new byte[args.size()][])); 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);
args.addAll(params.getParams());
sendCommand(SCAN, args.toArray(new byte[args.size()][]));
}
public void hscan(final byte[] key, final byte[] cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>();
args.add(key);
args.add(cursor);
args.addAll(params.getParams());
sendCommand(HSCAN, args.toArray(new byte[args.size()][]));
}
public void sscan(final byte[] key, final byte[] cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>();
args.add(key);
args.add(cursor);
args.addAll(params.getParams());
sendCommand(SSCAN, args.toArray(new byte[args.size()][]));
}
public void zscan(final byte[] key, final byte[] cursor, final ScanParams params) {
final List<byte[]> args = new ArrayList<byte[]>();
args.add(key);
args.add(cursor);
args.addAll(params.getParams());
sendCommand(ZSCAN, args.toArray(new byte[args.size()][]));
} }
public void waitReplicas(int replicas, long timeout) { public void waitReplicas(int replicas, long timeout) {
@@ -1137,9 +1253,26 @@ public class BinaryClient extends Connection {
} }
public void cluster(final byte[]... args) { public void cluster(final byte[]... args) {
sendCommand(CLUSTER, args); sendCommand(CLUSTER, args);
} }
public void asking() { public void asking() {
sendCommand(Command.ASKING); sendCommand(Command.ASKING);
}
public void pfadd(final byte[] key, final byte[]... elements) {
sendCommand(PFADD, joinParameters(key, elements));
}
public void pfcount(final byte[] key) {
sendCommand(PFCOUNT, key);
}
public void pfcount(final byte[]...keys) {
sendCommand(PFCOUNT, keys);
}
public void pfmerge(final byte[] destkey, final byte[]... sourcekeys) {
sendCommand(PFMERGE, joinParameters(destkey, sourcekeys));
} }
} }

View File

@@ -1,18 +1,31 @@
package redis.clients.jedis; package redis.clients.jedis;
import static redis.clients.jedis.Protocol.toByteArray;
import java.io.Closeable;
import java.net.URI;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.JedisByteHashMap; import redis.clients.util.JedisByteHashMap;
import redis.clients.util.SafeEncoder; import redis.clients.util.SafeEncoder;
import java.net.URI; public class BinaryJedis implements BasicCommands, BinaryJedisCommands,
import java.util.*; MultiKeyBinaryCommands, AdvancedBinaryJedisCommands,
BinaryScriptingCommands, Closeable {
import static redis.clients.jedis.Protocol.toByteArray;
public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKeyBinaryCommands, AdvancedBinaryJedisCommands, BinaryScriptingCommands {
protected Client client = null; protected Client client = null;
protected Transaction transaction = null;
protected Pipeline pipeline = null;
public BinaryJedis(final String host) { public BinaryJedis(final String host) {
URI uri = URI.create(host); URI uri = URI.create(host);
@@ -75,18 +88,23 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
/** /**
* Set the string value as value of the key. The string can't be longer than * Set the string value as value of the key. The string can't be longer than
* 1073741824 bytes (1 GB). * 1073741824 bytes (1 GB).
*
* @param key * @param key
* @param value * @param value
* @param nxxx NX|XX, NX -- Only set the key if it does not already exist. * @param nxxx
* XX -- Only set the key if it already exist. * NX|XX, NX -- Only set the key if it does not already exist. XX
* @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds * -- Only set the key if it already exist.
* @param time expire time in the units of {@param #expx} * @param expx
* EX|PX, expire time units: EX = seconds; PX = milliseconds
* @param time
* expire time in the units of {@param #expx}
* @return Status code reply * @return Status code reply
*/ */
public String set(final byte[] key, final byte[] value, final byte[] nxxx, final byte[] expx, final long time) { public String set(final byte[] key, final byte[] value, final byte[] nxxx,
checkIsInMulti(); final byte[] expx, final long time) {
client.set(key, value, nxxx, expx, time); checkIsInMulti();
return client.getStatusCodeReply(); client.set(key, value, nxxx, expx, time);
return client.getStatusCodeReply();
} }
/** /**
@@ -147,9 +165,9 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Long del(final byte[] key) { public Long del(final byte[] key) {
checkIsInMulti(); checkIsInMulti();
client.del(key); client.del(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
/** /**
@@ -619,6 +637,37 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getIntegerReply(); return client.getIntegerReply();
} }
/**
* INCRBYFLOAT work just like {@link #incrBy(byte[]) INCRBY} but increments
* by floats instead of integers.
* <p>
* 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
* negative value will work as expected.
* <p>
* Time complexity: O(1)
*
* @see #incr(byte[])
* @see #decr(byte[])
* @see #decrBy(byte[], long)
*
* @param key
* @param integer
* @return Integer reply, this commands will reply with the new value of key
* after the increment.
*/
public Double incrByFloat(final byte[] key, final double integer) {
checkIsInMulti();
client.incrByFloat(key, integer);
String dval = client.getBulkReply();
return (dval != null ? new Double(dval) : null);
}
/** /**
* Increment the number stored at key by one. If the key does not exist or * Increment the number stored at key by one. If the key does not exist or
* contains a value of a wrong type, set the key to the value of "0" before * contains a value of a wrong type, set the key to the value of "0" before
@@ -811,6 +860,33 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getIntegerReply(); return client.getIntegerReply();
} }
/**
* 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.
* <p>
* 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.
*/
public Double hincrByFloat(final byte[] key, final byte[] field,
final double value) {
checkIsInMulti();
client.hincrByFloat(key, field, value);
final String dval = client.getBulkReply();
return (dval != null ? new Double(dval) : null);
}
/** /**
* Test for existence of a specified field in a hash. * Test for existence of a specified field in a hash.
* *
@@ -1006,7 +1082,8 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
* @return Multi bulk reply, specifically a list of elements in the * @return Multi bulk reply, specifically a list of elements in the
* specified range. * specified range.
*/ */
public List<byte[]> lrange(final byte[] key, final long start, final long end) { public List<byte[]> lrange(final byte[] key, final long start,
final long end) {
checkIsInMulti(); checkIsInMulti();
client.lrange(key, start, end); client.lrange(key, start, end);
return client.getBinaryMultiBulkReply(); return client.getBinaryMultiBulkReply();
@@ -1470,9 +1547,9 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public List<byte[]> srandmember(final byte[] key, final int count) { public List<byte[]> srandmember(final byte[] key, final int count) {
checkIsInMulti(); checkIsInMulti();
client.srandmember(key, count); client.srandmember(key, count);
return client.getBinaryMultiBulkReply(); return client.getBinaryMultiBulkReply();
} }
/** /**
@@ -1502,7 +1579,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long zadd(final byte[] key, final Map<Double, byte[]> scoreMembers) { public Long zadd(final byte[] key, final Map<byte[], Double> scoreMembers) {
checkIsInMulti(); checkIsInMulti();
client.zaddBinary(key, scoreMembers); client.zaddBinary(key, scoreMembers);
return client.getIntegerReply(); return client.getIntegerReply();
@@ -1680,26 +1757,30 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
public Transaction multi() { public Transaction multi() {
client.multi(); client.multi();
client.getOne(); // expected OK client.getOne(); // expected OK
return new Transaction(client); transaction = new Transaction(client);
return transaction;
} }
@Deprecated
/**
* This method is deprecated due to its error prone
* and will be removed on next major release
* You can use multi() instead
* @see https://github.com/xetorthio/jedis/pull/498
*/
public List<Object> multi(final TransactionBlock jedisTransaction) { public List<Object> multi(final TransactionBlock jedisTransaction) {
List<Object> results = null; List<Object> results = null;
jedisTransaction.setClient(client); jedisTransaction.setClient(client);
try { client.multi();
client.multi(); client.getOne(); // expected OK
client.getOne(); // expected OK jedisTransaction.execute();
jedisTransaction.execute(); results = jedisTransaction.exec();
results = jedisTransaction.exec();
} catch (Exception ex) {
jedisTransaction.discard();
}
return results; return results;
} }
protected void checkIsInMulti() { protected void checkIsInMulti() {
if (client.isInMulti()) { if (client.isInMulti()) {
throw new JedisDataException( throw new JedisDataException(
"Cannot use Jedis when in Multi. Please use JedisTransaction instead."); "Cannot use Jedis when in Multi. Please use JedisTransaction instead.");
} }
} }
@@ -1712,6 +1793,27 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
client.disconnect(); client.disconnect();
} }
public void resetState() {
if (client.isConnected()) {
if (transaction != null) {
transaction.clear();
}
if (pipeline != null) {
pipeline.clear();
}
if (client.isInWatch()) {
unwatch();
}
client.resetState();
}
transaction = null;
pipeline = null;
}
public String watch(final byte[]... keys) { public String watch(final byte[]... keys) {
client.watch(keys); client.watch(keys);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
@@ -1722,6 +1824,11 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
@Override
public void close() {
client.close();
}
/** /**
* Sort a Set or a List. * Sort a Set or a List.
* <p> * <p>
@@ -2046,43 +2153,43 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public List<byte[]> blpop(byte[] arg) { public List<byte[]> blpop(byte[] arg) {
checkIsInMulti(); checkIsInMulti();
byte[][] args = new byte[1][]; byte[][] args = new byte[1][];
args[0] = arg; args[0] = arg;
client.blpop(args); client.blpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply(); final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<byte[]> brpop(byte[] arg) { public List<byte[]> brpop(byte[] arg) {
checkIsInMulti(); checkIsInMulti();
byte[][] args = new byte[1][]; byte[][] args = new byte[1][];
args[0] = arg; args[0] = arg;
client.brpop(args); client.brpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply(); final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<byte[]> blpop(byte[]... args) { public List<byte[]> blpop(byte[]... args) {
checkIsInMulti(); checkIsInMulti();
client.blpop(args); client.blpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply(); final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<byte[]> brpop(byte[]... args) { public List<byte[]> brpop(byte[]... args) {
checkIsInMulti(); checkIsInMulti();
client.brpop(args); client.brpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply(); final List<byte[]> multiBulkReply = client.getBinaryMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
/** /**
@@ -2106,14 +2213,12 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
@Deprecated
/** /**
* Starts a pipeline, which is a very efficient way to send lots of command * This method is deprecated due to its error prone with multi
* and read all the responses when you finish sending them. Try to avoid * and will be removed on next major release
* this version and use pipelined() when possible as it will give better * You can use pipelined() instead
* performance. * @see https://github.com/xetorthio/jedis/pull/498
*
* @param jedisPipeline
* @return The results of the command in the same order you've run them.
*/ */
public List<Object> pipelined(final PipelineBlock jedisPipeline) { public List<Object> pipelined(final PipelineBlock jedisPipeline) {
jedisPipeline.setClient(client); jedisPipeline.setClient(client);
@@ -2122,19 +2227,19 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Pipeline pipelined() { public Pipeline pipelined() {
Pipeline pipeline = new Pipeline(); pipeline = new Pipeline();
pipeline.setClient(client); pipeline.setClient(client);
return pipeline; return pipeline;
} }
public Long zcount(final byte[] key, final double min, final double max) { public Long zcount(final byte[] key, final double min, final double max) {
return zcount(key, toByteArray(min), toByteArray(max)); return zcount(key, toByteArray(min), toByteArray(max));
} }
public Long zcount(final byte[] key, final byte[] min, final byte[] max) { public Long zcount(final byte[] key, final byte[] min, final byte[] max) {
checkIsInMulti(); checkIsInMulti();
client.zcount(key, min, max); client.zcount(key, min, max);
return client.getIntegerReply(); return client.getIntegerReply();
} }
/** /**
@@ -2196,7 +2301,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
public Set<byte[]> zrangeByScore(final byte[] key, final double min, public Set<byte[]> zrangeByScore(final byte[] key, final double min,
final double max) { final double max) {
return zrangeByScore(key, toByteArray(min), toByteArray(max)); return zrangeByScore(key, toByteArray(min), toByteArray(max));
} }
public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min,
final byte[] max) { final byte[] max) {
@@ -2263,15 +2368,16 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
*/ */
public Set<byte[]> zrangeByScore(final byte[] key, final double min, public Set<byte[]> zrangeByScore(final byte[] key, final double min,
final double max, final int offset, final int count) { final double max, final int offset, final int count) {
return zrangeByScore(key, toByteArray(min),toByteArray(max),offset, count); return zrangeByScore(key, toByteArray(min), toByteArray(max), offset,
count);
} }
public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min, public Set<byte[]> zrangeByScore(final byte[] key, final byte[] min,
final byte[] max, final int offset, final int count) { final byte[] max, final int offset, final int count) {
checkIsInMulti(); checkIsInMulti();
client.zrangeByScore(key, min, max, offset, count); client.zrangeByScore(key, min, max, offset, count);
return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply()); return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply());
} }
/** /**
* Return the all the elements in the sorted set at key with a score between * Return the all the elements in the sorted set at key with a score between
@@ -2335,12 +2441,12 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrangeByScoreWithScores(final byte[] key,
final byte[] min, final byte[] max) { final byte[] min, final byte[] max) {
checkIsInMulti(); checkIsInMulti();
client.zrangeByScoreWithScores(key, min, max); client.zrangeByScoreWithScores(key, min, max);
Set<Tuple> set = getBinaryTupledSet(); Set<Tuple> set = getBinaryTupledSet();
return set; return set;
} }
/** /**
* Return the all the elements in the sorted set at key with a score between * Return the all the elements in the sorted set at key with a score between
@@ -2401,17 +2507,18 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrangeByScoreWithScores(final byte[] key,
final double min, final double max, final int offset, final double min, final double max, final int offset,
final int count) { final int count) {
return zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max), offset, count); return zrangeByScoreWithScores(key, toByteArray(min), toByteArray(max),
offset, count);
} }
public Set<Tuple> zrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrangeByScoreWithScores(final byte[] key,
final byte[] min, final byte[] max, final int offset, final byte[] min, final byte[] max, final int offset,
final int count) { final int count) {
checkIsInMulti(); checkIsInMulti();
client.zrangeByScoreWithScores(key, min, max, offset, count); client.zrangeByScoreWithScores(key, min, max, offset, count);
Set<Tuple> set = getBinaryTupledSet(); Set<Tuple> set = getBinaryTupledSet();
return set; return set;
} }
private Set<Tuple> getBinaryTupledSet() { private Set<Tuple> getBinaryTupledSet() {
checkIsInMulti(); checkIsInMulti();
@@ -2439,29 +2546,32 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
public Set<byte[]> zrevrangeByScore(final byte[] key, final double max, public Set<byte[]> zrevrangeByScore(final byte[] key, final double max,
final double min, final int offset, final int count) { final double min, final int offset, final int count) {
return zrevrangeByScore(key, toByteArray(max), toByteArray(min), offset, count); return zrevrangeByScore(key, toByteArray(max), toByteArray(min),
offset, count);
} }
public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max, public Set<byte[]> zrevrangeByScore(final byte[] key, final byte[] max,
final byte[] min, final int offset, final int count) { final byte[] min, final int offset, final int count) {
checkIsInMulti(); checkIsInMulti();
client.zrevrangeByScore(key, max, min, offset, count); client.zrevrangeByScore(key, max, min, offset, count);
return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply()); return new LinkedHashSet<byte[]>(client.getBinaryMultiBulkReply());
} }
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key,
final double max, final double min) { final double max, final double min) {
return zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min)); return zrevrangeByScoreWithScores(key, toByteArray(max),
toByteArray(min));
} }
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key,
final double max, final double min, final int offset, final double max, final double min, final int offset,
final int count) { final int count) {
return zrevrangeByScoreWithScores(key, toByteArray(max), toByteArray(min), offset, count); return zrevrangeByScoreWithScores(key, toByteArray(max),
toByteArray(min), offset, count);
} }
public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key, public Set<Tuple> zrevrangeByScoreWithScores(final byte[] key,
final byte[] max, final byte[] min) { final byte[] max, final byte[] min) {
checkIsInMulti(); checkIsInMulti();
client.zrevrangeByScoreWithScores(key, max, min); client.zrevrangeByScoreWithScores(key, max, min);
Set<Tuple> set = getBinaryTupledSet(); Set<Tuple> set = getBinaryTupledSet();
@@ -2490,7 +2600,8 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
* operation * operation
* *
*/ */
public Long zremrangeByRank(final byte[] key, final long start, final long end) { public Long zremrangeByRank(final byte[] key, final long start,
final long end) {
checkIsInMulti(); checkIsInMulti();
client.zremrangeByRank(key, start, end); client.zremrangeByRank(key, start, end);
return client.getIntegerReply(); return client.getIntegerReply();
@@ -2516,11 +2627,11 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Long zremrangeByScore(final byte[] key, final byte[] start, public Long zremrangeByScore(final byte[] key, final byte[] start,
final byte[] end) { final byte[] end) {
checkIsInMulti(); checkIsInMulti();
client.zremrangeByScore(key, start, end); client.zremrangeByScore(key, start, end);
return client.getIntegerReply(); return client.getIntegerReply();
} }
/** /**
* Creates a union or intersection of N sorted sets given by keys k1 through * Creates a union or intersection of N sorted sets given by keys k1 through
@@ -3080,8 +3191,8 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Boolean setbit(byte[] key, long offset, byte[] value) { public Boolean setbit(byte[] key, long offset, byte[] value) {
client.setbit(key, offset, value); client.setbit(key, offset, value);
return client.getIntegerReply() == 1; return client.getIntegerReply() == 1;
} }
/** /**
@@ -3096,6 +3207,16 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
return client.getIntegerReply() == 1; return client.getIntegerReply() == 1;
} }
public Long bitpos(final byte[] key, final boolean value) {
return bitpos(key, value, new BitPosParams());
}
public Long bitpos(final byte[] key, final boolean value,
final BitPosParams params) {
client.bitpos(key, value, params);
return client.getIntegerReply();
}
public Long setrange(byte[] key, long offset, byte[] value) { public Long setrange(byte[] key, long offset, byte[] value) {
client.setrange(key, offset, value); client.setrange(key, offset, value);
return client.getIntegerReply(); return client.getIntegerReply();
@@ -3142,12 +3263,13 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
private byte[][] getParams(List<byte[]> keys, List<byte[]> args) { private byte[][] getParams(List<byte[]> keys, List<byte[]> args) {
int keyCount = keys.size(); int keyCount = keys.size();
int argCount = args.size();
byte[][] params = new byte[keyCount + args.size()][]; byte[][] params = new byte[keyCount + args.size()][];
for (int i = 0; i < keyCount; i++) for (int i = 0; i < keyCount; i++)
params[i] = keys.get(i); params[i] = keys.get(i);
for (int i = 0; i < keys.size(); i++) for (int i = 0; i < argCount; i++)
params[keyCount + i] = args.get(i); params[keyCount + i] = args.get(i);
return params; return params;
@@ -3160,44 +3282,44 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Object eval(byte[] script, int keyCount, byte[]... params) { public Object eval(byte[] script, int keyCount, byte[]... params) {
client.setTimeoutInfinite(); client.setTimeoutInfinite();
client.eval(script, SafeEncoder.encode(Integer.toString(keyCount)), params); client.eval(script, SafeEncoder.encode(Integer.toString(keyCount)),
return client.getOne(); params);
return client.getOne();
} }
public Object eval(byte[] script) { public Object eval(byte[] script) {
client.setTimeoutInfinite(); client.setTimeoutInfinite();
client.eval(script, 0); client.eval(script, 0);
return client.getOne(); return client.getOne();
} }
public Object evalsha(byte[] sha1) { public Object evalsha(byte[] sha1) {
client.setTimeoutInfinite(); client.setTimeoutInfinite();
client.evalsha(sha1, 0); client.evalsha(sha1, 0);
return client.getOne(); return client.getOne();
} }
public Object evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args) { public Object evalsha(byte[] sha1, List<byte[]> keys, List<byte[]> args) {
int keyCount = keys == null ? 0 : keys.size(); int keyCount = keys == null ? 0 : keys.size();
int argCount = args == null ? 0 : args.size(); int argCount = args == null ? 0 : args.size();
byte[][] params = new byte[keyCount + argCount][]; byte[][] params = new byte[keyCount + argCount][];
for (int i = 0; i < keyCount; i++) for (int i = 0; i < keyCount; i++)
params[i] = keys.get(i); params[i] = keys.get(i);
for (int i = 0; i < argCount; i++) for (int i = 0; i < argCount; i++)
params[keyCount + i] = args.get(i); params[keyCount + i] = args.get(i);
return evalsha(sha1, keyCount, params);
return evalsha(sha1, keyCount, params); }
}
public Object evalsha(byte[] sha1, int keyCount, byte[]... params) { public Object evalsha(byte[] sha1, int keyCount, byte[]... params) {
client.setTimeoutInfinite(); client.setTimeoutInfinite();
client.evalsha(sha1, keyCount, params); client.evalsha(sha1, keyCount, params);
return client.getOne(); return client.getOne();
} }
public String scriptFlush() { public String scriptFlush() {
@@ -3207,7 +3329,7 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
public List<Long> scriptExists(byte[]... sha1) { public List<Long> scriptExists(byte[]... sha1) {
client.scriptExists(sha1); client.scriptExists(sha1);
return client.getIntegerMultiBulkReply(); return client.getIntegerMultiBulkReply();
} }
public byte[] scriptLoad(byte[] script) { public byte[] scriptLoad(byte[] script) {
@@ -3241,131 +3363,126 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
} }
public Long objectRefcount(byte[] key) { public Long objectRefcount(byte[] key) {
client.objectRefcount(key); client.objectRefcount(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public byte[] objectEncoding(byte[] key) { public byte[] objectEncoding(byte[] key) {
client.objectEncoding(key); client.objectEncoding(key);
return client.getBinaryBulkReply(); return client.getBinaryBulkReply();
} }
public Long objectIdletime(byte[] key) { public Long objectIdletime(byte[] key) {
client.objectIdletime(key); client.objectIdletime(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long bitcount(final byte[] key) { public Long bitcount(final byte[] key) {
client.bitcount(key); client.bitcount(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long bitcount(final byte[] key, long start, long end) { public Long bitcount(final byte[] key, long start, long end) {
client.bitcount(key, start, end); client.bitcount(key, start, end);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys) { public Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys) {
client.bitop(op, destKey, srcKeys); client.bitop(op, destKey, srcKeys);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public byte[] dump(final byte[] key) { public byte[] dump(final byte[] key) {
checkIsInMulti(); checkIsInMulti();
client.dump(key); client.dump(key);
return client.getBinaryBulkReply(); return client.getBinaryBulkReply();
} }
public String restore(final byte[] key, final int ttl, final byte[] serializedValue) { public String restore(final byte[] key, final int ttl,
checkIsInMulti(); final byte[] serializedValue) {
client.restore(key, ttl, serializedValue); checkIsInMulti();
return client.getStatusCodeReply(); client.restore(key, ttl, serializedValue);
return client.getStatusCodeReply();
} }
@Deprecated
public Long pexpire(final byte[] key, final int milliseconds) { public Long pexpire(final byte[] key, final int milliseconds) {
checkIsInMulti(); return pexpire(key, (long) milliseconds);
client.pexpire(key, milliseconds); }
return client.getIntegerReply();
public Long pexpire(final byte[] key, final long milliseconds) {
checkIsInMulti();
client.pexpire(key, milliseconds);
return client.getIntegerReply();
} }
public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) { public Long pexpireAt(final byte[] key, final long millisecondsTimestamp) {
checkIsInMulti(); checkIsInMulti();
client.pexpireAt(key, millisecondsTimestamp); client.pexpireAt(key, millisecondsTimestamp);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long pttl(final byte[] key) { public Long pttl(final byte[] key) {
checkIsInMulti(); checkIsInMulti();
client.pttl(key); client.pttl(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Double incrByFloat(final byte[] key, final double increment) { public String psetex(final byte[] key, final int milliseconds,
checkIsInMulti(); final byte[] value) {
client.incrByFloat(key, increment); checkIsInMulti();
String relpy = client.getBulkReply(); client.psetex(key, milliseconds, value);
return (relpy != null ? new Double(relpy) : null); return client.getStatusCodeReply();
}
public String psetex(final byte[] key, final int milliseconds, final byte[] value) {
checkIsInMulti();
client.psetex(key, milliseconds, value);
return client.getStatusCodeReply();
} }
public String set(final byte[] key, final byte[] value, final byte[] nxxx) { public String set(final byte[] key, final byte[] value, final byte[] nxxx) {
checkIsInMulti(); checkIsInMulti();
client.set(key, value, nxxx); client.set(key, value, nxxx);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String set(final byte[] key, final byte[] value, final byte[] nxxx, final byte[] expx, final int time) { public String set(final byte[] key, final byte[] value, final byte[] nxxx,
checkIsInMulti(); final byte[] expx, final int time) {
client.set(key, value, nxxx, expx, time); checkIsInMulti();
return client.getStatusCodeReply(); client.set(key, value, nxxx, expx, time);
return client.getStatusCodeReply();
} }
public String clientKill(final byte[] client) { public String clientKill(final byte[] client) {
checkIsInMulti(); checkIsInMulti();
this.client.clientKill(client); this.client.clientKill(client);
return this.client.getStatusCodeReply(); return this.client.getStatusCodeReply();
} }
public String clientGetname() { public String clientGetname() {
checkIsInMulti(); checkIsInMulti();
client.clientGetname(); client.clientGetname();
return client.getBulkReply(); return client.getBulkReply();
} }
public String clientList() { public String clientList() {
checkIsInMulti(); checkIsInMulti();
client.clientList(); client.clientList();
return client.getBulkReply(); return client.getBulkReply();
} }
public String clientSetname(final byte[] name) { public String clientSetname(final byte[] name) {
checkIsInMulti(); checkIsInMulti();
client.clientSetname(name); client.clientSetname(name);
return client.getBulkReply(); return client.getBulkReply();
} }
public List<String> time() { public List<String> time() {
checkIsInMulti(); checkIsInMulti();
client.time(); client.time();
return client.getMultiBulkReply(); return client.getMultiBulkReply();
} }
public String migrate(final byte[] host, final int port, final byte[] key, final int destinationDb, final int timeout) { public String migrate(final byte[] host, final int port, final byte[] key,
checkIsInMulti(); final int destinationDb, final int timeout) {
client.migrate(host, port, key, destinationDb, timeout); checkIsInMulti();
return client.getStatusCodeReply(); client.migrate(host, port, key, destinationDb, timeout);
} return client.getStatusCodeReply();
public Double hincrByFloat(final byte[] key, final byte[] field, double increment) {
checkIsInMulti();
client.hincrByFloat(key, field, increment);
String relpy = client.getBulkReply();
return (relpy != null ? new Double(relpy) : null);
} }
/** /**
@@ -3376,9 +3493,104 @@ public class BinaryJedis implements BasicCommands, BinaryJedisCommands, MultiKey
* so I had to change the name of the method. Sorry :S * so I had to change the name of the method. Sorry :S
*/ */
public Long waitReplicas(int replicas, long timeout) { public Long waitReplicas(int replicas, long timeout) {
checkIsInMulti(); checkIsInMulti();
client.waitReplicas(replicas, timeout); client.waitReplicas(replicas, timeout);
return client.getIntegerReply(); return client.getIntegerReply();
} }
@Override
public Long pfadd(final byte[] key, final byte[]... elements) {
checkIsInMulti();
client.pfadd(key, elements);
return client.getIntegerReply();
}
@Override
public long pfcount(final byte[] key) {
checkIsInMulti();
client.pfcount(key);
return client.getIntegerReply();
}
@Override
public String pfmerge(final byte[] destkey, final byte[]... sourcekeys) {
checkIsInMulti();
client.pfmerge(destkey, sourcekeys);
return client.getStatusCodeReply();
}
@Override
public Long pfcount(byte[]... keys) {
checkIsInMulti();
client.pfcount(keys);
return client.getIntegerReply();
}
public ScanResult<byte[]> scan(final byte[] cursor) {
return scan(cursor, new ScanParams());
}
public ScanResult<byte[]> scan(final byte[] cursor, final ScanParams params) {
checkIsInMulti();
client.scan(cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
byte[] newcursor = (byte[]) result.get(0);
List<byte[]> rawResults = (List<byte[]>) result.get(1);
return new ScanResult<byte[]>(newcursor, rawResults);
}
public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key,
final byte[] cursor) {
return hscan(key, cursor, new ScanParams());
}
public ScanResult<Map.Entry<byte[], byte[]>> hscan(final byte[] key,
final byte[] cursor, final ScanParams params) {
checkIsInMulti();
client.hscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
byte[] newcursor = (byte[]) result.get(0);
List<Map.Entry<byte[], byte[]>> results = new ArrayList<Map.Entry<byte[], byte[]>>();
List<byte[]> rawResults = (List<byte[]>) result.get(1);
Iterator<byte[]> iterator = rawResults.iterator();
while (iterator.hasNext()) {
results.add(new AbstractMap.SimpleEntry<byte[], byte[]>(iterator
.next(), iterator.next()));
}
return new ScanResult<Map.Entry<byte[], byte[]>>(newcursor, results);
}
public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor) {
return sscan(key, cursor, new ScanParams());
}
public ScanResult<byte[]> sscan(final byte[] key, final byte[] cursor,
final ScanParams params) {
checkIsInMulti();
client.sscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
byte[] newcursor = (byte[]) result.get(0);
List<byte[]> rawResults = (List<byte[]>) result.get(1);
return new ScanResult<byte[]>(newcursor, rawResults);
}
public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor) {
return zscan(key, cursor, new ScanParams());
}
public ScanResult<Tuple> zscan(final byte[] key, final byte[] cursor,
final ScanParams params) {
checkIsInMulti();
client.zscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
byte[] newcursor = (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(iterator.next(), Double.valueOf(SafeEncoder
.encode(iterator.next()))));
}
return new ScanResult<Tuple>(newcursor, results);
}
} }

View File

@@ -47,6 +47,8 @@ public interface BinaryJedisCommands {
Long incrBy(byte[] key, long integer); Long incrBy(byte[] key, long integer);
Double incrByFloat(byte[] key, double value);
Long incr(byte[] key); Long incr(byte[] key);
Long append(byte[] key, byte[] value); Long append(byte[] key, byte[] value);
@@ -65,6 +67,8 @@ public interface BinaryJedisCommands {
Long hincrBy(byte[] key, byte[] field, long value); Long hincrBy(byte[] key, byte[] field, long value);
Double hincrByFloat(byte[] key, byte[] field, double value);
Boolean hexists(byte[] key, byte[] field); Boolean hexists(byte[] key, byte[] field);
Long hdel(byte[] key, byte[]... field); Long hdel(byte[] key, byte[]... field);
@@ -115,7 +119,7 @@ public interface BinaryJedisCommands {
Long zadd(byte[] key, double score, byte[] member); Long zadd(byte[] key, double score, byte[] member);
Long zadd(byte[] key, Map<Double, byte[]> scoreMembers); Long zadd(byte[] key, Map<byte[], Double> scoreMembers);
Set<byte[]> zrange(byte[] key, long start, long end); Set<byte[]> zrange(byte[] key, long start, long end);
@@ -211,4 +215,8 @@ public interface BinaryJedisCommands {
Long bitcount(final byte[] key); Long bitcount(final byte[] key);
Long bitcount(final byte[] key, long start, long end); Long bitcount(final byte[] key, long start, long end);
Long pfadd(final byte[] key, final byte[]... elements);
long pfcount(final byte[] key);
} }

View File

@@ -19,7 +19,7 @@ public abstract class BinaryJedisPubSub {
public abstract void onMessage(byte[] channel, byte[] message); public abstract void onMessage(byte[] channel, byte[] message);
public abstract void onPMessage(byte[] pattern, byte[] channel, public abstract void onPMessage(byte[] pattern, byte[] channel,
byte[] message); byte[] message);
public abstract void onSubscribe(byte[] channel, int subscribedChannels); public abstract void onSubscribe(byte[] channel, int subscribedChannels);
@@ -30,91 +30,91 @@ public abstract class BinaryJedisPubSub {
public abstract void onPSubscribe(byte[] pattern, int subscribedChannels); public abstract void onPSubscribe(byte[] pattern, int subscribedChannels);
public void unsubscribe() { public void unsubscribe() {
client.unsubscribe(); client.unsubscribe();
client.flush(); client.flush();
} }
public void unsubscribe(byte[]... channels) { public void unsubscribe(byte[]... channels) {
client.unsubscribe(channels); client.unsubscribe(channels);
client.flush(); client.flush();
} }
public void subscribe(byte[]... channels) { public void subscribe(byte[]... channels) {
client.subscribe(channels); client.subscribe(channels);
client.flush(); client.flush();
} }
public void psubscribe(byte[]... patterns) { public void psubscribe(byte[]... patterns) {
client.psubscribe(patterns); client.psubscribe(patterns);
client.flush(); client.flush();
} }
public void punsubscribe() { public void punsubscribe() {
client.punsubscribe(); client.punsubscribe();
client.flush(); client.flush();
} }
public void punsubscribe(byte[]... patterns) { public void punsubscribe(byte[]... patterns) {
client.punsubscribe(patterns); client.punsubscribe(patterns);
client.flush(); client.flush();
} }
public boolean isSubscribed() { public boolean isSubscribed() {
return subscribedChannels > 0; return subscribedChannels > 0;
} }
public void proceedWithPatterns(Client client, byte[]... patterns) { public void proceedWithPatterns(Client client, byte[]... patterns) {
this.client = client; this.client = client;
client.psubscribe(patterns); client.psubscribe(patterns);
process(client); process(client);
} }
public void proceed(Client client, byte[]... channels) { public void proceed(Client client, byte[]... channels) {
this.client = client; this.client = client;
client.subscribe(channels); client.subscribe(channels);
process(client); process(client);
} }
private void process(Client client) { private void process(Client client) {
do { do {
List<Object> reply = client.getObjectMultiBulkReply(); List<Object> reply = client.getObjectMultiBulkReply();
final Object firstObj = reply.get(0); final Object firstObj = reply.get(0);
if (!(firstObj instanceof byte[])) { if (!(firstObj instanceof byte[])) {
throw new JedisException("Unknown message type: " + firstObj); throw new JedisException("Unknown message type: " + firstObj);
} }
final byte[] resp = (byte[]) firstObj; final byte[] resp = (byte[]) firstObj;
if (Arrays.equals(SUBSCRIBE.raw, resp)) { if (Arrays.equals(SUBSCRIBE.raw, resp)) {
subscribedChannels = ((Long) reply.get(2)).intValue(); subscribedChannels = ((Long) reply.get(2)).intValue();
final byte[] bchannel = (byte[]) reply.get(1); final byte[] bchannel = (byte[]) reply.get(1);
onSubscribe(bchannel, subscribedChannels); onSubscribe(bchannel, subscribedChannels);
} else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) {
subscribedChannels = ((Long) reply.get(2)).intValue(); subscribedChannels = ((Long) reply.get(2)).intValue();
final byte[] bchannel = (byte[]) reply.get(1); final byte[] bchannel = (byte[]) reply.get(1);
onUnsubscribe(bchannel, subscribedChannels); onUnsubscribe(bchannel, subscribedChannels);
} else if (Arrays.equals(MESSAGE.raw, resp)) { } else if (Arrays.equals(MESSAGE.raw, resp)) {
final byte[] bchannel = (byte[]) reply.get(1); final byte[] bchannel = (byte[]) reply.get(1);
final byte[] bmesg = (byte[]) reply.get(2); final byte[] bmesg = (byte[]) reply.get(2);
onMessage(bchannel, bmesg); onMessage(bchannel, bmesg);
} else if (Arrays.equals(PMESSAGE.raw, resp)) { } else if (Arrays.equals(PMESSAGE.raw, resp)) {
final byte[] bpattern = (byte[]) reply.get(1); final byte[] bpattern = (byte[]) reply.get(1);
final byte[] bchannel = (byte[]) reply.get(2); final byte[] bchannel = (byte[]) reply.get(2);
final byte[] bmesg = (byte[]) reply.get(3); final byte[] bmesg = (byte[]) reply.get(3);
onPMessage(bpattern, bchannel, bmesg); onPMessage(bpattern, bchannel, bmesg);
} else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) {
subscribedChannels = ((Long) reply.get(2)).intValue(); subscribedChannels = ((Long) reply.get(2)).intValue();
final byte[] bpattern = (byte[]) reply.get(1); final byte[] bpattern = (byte[]) reply.get(1);
onPSubscribe(bpattern, subscribedChannels); onPSubscribe(bpattern, subscribedChannels);
} else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) {
subscribedChannels = ((Long) reply.get(2)).intValue(); subscribedChannels = ((Long) reply.get(2)).intValue();
final byte[] bpattern = (byte[]) reply.get(1); final byte[] bpattern = (byte[]) reply.get(1);
onPUnsubscribe(bpattern, subscribedChannels); onPUnsubscribe(bpattern, subscribedChannels);
} else { } else {
throw new JedisException("Unknown message type: " + firstObj); throw new JedisException("Unknown message type: " + firstObj);
} }
} while (isSubscribed()); } while (isSubscribed());
} }
public int getSubscribedChannels() { public int getSubscribedChannels() {
return subscribedChannels; return subscribedChannels;
} }
} }

View File

@@ -67,7 +67,7 @@ public interface BinaryRedisPipeline {
Response<byte[]> lindex(byte[] key, long index); Response<byte[]> lindex(byte[] key, long index);
Response<Long> linsert(byte[] key, BinaryClient.LIST_POSITION where, Response<Long> linsert(byte[] key, BinaryClient.LIST_POSITION where,
byte[] pivot, byte[] value); byte[] pivot, byte[] value);
Response<Long> llen(byte[] key); Response<Long> llen(byte[] key);
@@ -117,8 +117,7 @@ public interface BinaryRedisPipeline {
Response<List<byte[]>> sort(byte[] key); Response<List<byte[]>> sort(byte[] key);
Response<List<byte[]>> sort(byte[] key, Response<List<byte[]>> sort(byte[] key, SortingParams sortingParameters);
SortingParams sortingParameters);
Response<byte[]> spop(byte[] key); Response<byte[]> spop(byte[] key);
@@ -144,53 +143,49 @@ public interface BinaryRedisPipeline {
Response<Set<byte[]>> zrange(byte[] key, long start, long end); Response<Set<byte[]>> zrange(byte[] key, long start, long end);
Response<Set<byte[]>> zrangeByScore(byte[] key, double min, Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max);
double max);
Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max);
byte[] max);
Response<Set<byte[]>> zrangeByScore(byte[] key, double min, Response<Set<byte[]>> zrangeByScore(byte[] key, double min, double max,
double max, int offset, int count); int offset, int count);
Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, Response<Set<byte[]>> zrangeByScore(byte[] key, byte[] min, byte[] max,
byte[] max, int offset, int count); int offset, int count);
Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min,
double max); double max);
Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min,
byte[] max); byte[] max);
Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min, Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, double min,
double max, int offset, int count); double max, int offset, int count);
Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min, Response<Set<Tuple>> zrangeByScoreWithScores(byte[] key, byte[] min,
byte[] max, int offset, int count); byte[] max, int offset, int count);
Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min);
double min);
Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min);
byte[] min);
Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, Response<Set<byte[]>> zrevrangeByScore(byte[] key, double max, double min,
double min, int offset, int count); int offset, int count);
Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, Response<Set<byte[]>> zrevrangeByScore(byte[] key, byte[] max, byte[] min,
byte[] min, int offset, int count); int offset, int count);
Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max,
double max, double min); double min);
Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max,
byte[] max, byte[] min); byte[] min);
Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, double max,
double max, double min, int offset, int count); double min, int offset, int count);
Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, Response<Set<Tuple>> zrevrangeByScoreWithScores(byte[] key, byte[] max,
byte[] max, byte[] min, int offset, int count); byte[] min, int offset, int count);
Response<Set<Tuple>> zrangeWithScores(byte[] key, long start, long end); Response<Set<Tuple>> zrangeWithScores(byte[] key, long start, long end);
@@ -206,8 +201,7 @@ public interface BinaryRedisPipeline {
Response<Set<byte[]>> zrevrange(byte[] key, long start, long end); Response<Set<byte[]>> zrevrange(byte[] key, long start, long end);
Response<Set<Tuple>> zrevrangeWithScores(byte[] key, long start, Response<Set<Tuple>> zrevrangeWithScores(byte[] key, long start, long end);
long end);
Response<Long> zrevrank(byte[] key, byte[] member); Response<Long> zrevrank(byte[] key, byte[] member);
@@ -216,4 +210,8 @@ public interface BinaryRedisPipeline {
Response<Long> bitcount(byte[] key); Response<Long> bitcount(byte[] key);
Response<Long> bitcount(byte[] key, long start, long end); Response<Long> bitcount(byte[] key, long start, long end);
Response<Long> pfadd(final byte[] key, final byte[]... elements);
Response<Long> pfcount(final byte[] key);
} }

View File

@@ -1,6 +1,5 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
public interface BinaryScriptingCommands { public interface BinaryScriptingCommands {

View File

@@ -110,6 +110,11 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
return j.incrBy(key, integer); return j.incrBy(key, integer);
} }
public Double incrByFloat(byte[] key, double integer) {
Jedis j = getShard(key);
return j.incrByFloat(key, integer);
}
public Long incr(byte[] key) { public Long incr(byte[] key) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.incr(key); return j.incr(key);
@@ -155,6 +160,11 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
return j.hincrBy(key, field, value); return j.hincrBy(key, field, value);
} }
public Double hincrByFloat(byte[] key, byte[] field, double value) {
Jedis j = getShard(key);
return j.hincrByFloat(key, field, value);
}
public Boolean hexists(byte[] key, byte[] field) { public Boolean hexists(byte[] key, byte[] field) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.hexists(key, field); return j.hexists(key, field);
@@ -295,7 +305,7 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
return j.zadd(key, score, member); return j.zadd(key, score, member);
} }
public Long zadd(byte[] key, Map<Double, byte[]> scoreMembers) { public Long zadd(byte[] key, Map<byte[], Double> scoreMembers) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.zadd(key, scoreMembers); return j.zadd(key, scoreMembers);
} }
@@ -482,6 +492,12 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
} }
@Deprecated @Deprecated
/**
* This method is deprecated due to its error prone with multi
* and will be removed on next major release
* You can use pipelined() instead
* @see https://github.com/xetorthio/jedis/pull/498
*/
public List<Object> pipelined(ShardedJedisPipeline shardedJedisPipeline) { public List<Object> pipelined(ShardedJedisPipeline shardedJedisPipeline) {
shardedJedisPipeline.setShardedJedis(this); shardedJedisPipeline.setShardedJedis(this);
shardedJedisPipeline.execute(); shardedJedisPipeline.execute();
@@ -563,4 +579,17 @@ public class BinaryShardedJedis extends Sharded<Jedis, JedisShardInfo>
Jedis j = getShard(key); Jedis j = getShard(key);
return j.bitcount(key, start, end); return j.bitcount(key, start, end);
} }
@Override
public Long pfadd(final byte[] key, final byte[]... elements) {
Jedis j = getShard(key);
return j.pfadd(key, elements);
}
@Override
public long pfcount(final byte[] key) {
Jedis j = getShard(key);
return j.pfcount(key);
}
} }

View File

@@ -1,8 +1,5 @@
package redis.clients.jedis; package redis.clients.jedis;
public enum BitOP { public enum BitOP {
AND, AND, OR, XOR, NOT;
OR,
XOR,
NOT;
} }

View File

@@ -0,0 +1,27 @@
package redis.clients.jedis;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
public class BitPosParams {
private List<byte[]> params = new ArrayList<byte[]>();
protected BitPosParams() {
}
public BitPosParams(long start) {
params.add(Protocol.toByteArray(start));
}
public BitPosParams(long start, long end) {
this(start);
params.add(Protocol.toByteArray(end));
}
public Collection<byte[]> getParams() {
return Collections.unmodifiableCollection(params);
}
}

View File

@@ -1,249 +1,257 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.util.SafeEncoder; import redis.clients.util.SafeEncoder;
import java.util.*;
public class BuilderFactory { public class BuilderFactory {
public static final Builder<Double> DOUBLE = new Builder<Double>() { public static final Builder<Double> DOUBLE = new Builder<Double>() {
public Double build(Object data) { public Double build(Object data) {
String asString = STRING.build(data); String asString = STRING.build(data);
return asString == null ? null : Double.valueOf(asString); return asString == null ? null : Double.valueOf(asString);
} }
public String toString() { public String toString() {
return "double"; return "double";
} }
}; };
public static final Builder<Boolean> BOOLEAN = new Builder<Boolean>() { public static final Builder<Boolean> BOOLEAN = new Builder<Boolean>() {
public Boolean build(Object data) { public Boolean build(Object data) {
return ((Long) data) == 1; return ((Long) data) == 1;
} }
public String toString() { public String toString() {
return "boolean"; return "boolean";
} }
}; };
public static final Builder<byte[]> BYTE_ARRAY = new Builder<byte[]>() { public static final Builder<byte[]> BYTE_ARRAY = new Builder<byte[]>() {
public byte[] build(Object data) { public byte[] build(Object data) {
return ((byte[]) data); // deleted == 1 return ((byte[]) data); // deleted == 1
} }
public String toString() { public String toString() {
return "byte[]"; return "byte[]";
} }
}; };
public static final Builder<Long> LONG = new Builder<Long>() { public static final Builder<Long> LONG = new Builder<Long>() {
public Long build(Object data) { public Long build(Object data) {
return (Long) data; return (Long) data;
} }
public String toString() { public String toString() {
return "long"; return "long";
} }
}; };
public static final Builder<String> STRING = new Builder<String>() { public static final Builder<String> STRING = new Builder<String>() {
public String build(Object data) { public String build(Object data) {
return data == null ? null : SafeEncoder.encode((byte[]) data); return data == null ? null : SafeEncoder.encode((byte[]) data);
} }
public String toString() { public String toString() {
return "string"; return "string";
} }
}; };
public static final Builder<List<String>> STRING_LIST = new Builder<List<String>>() { public static final Builder<List<String>> STRING_LIST = new Builder<List<String>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<String> build(Object data) { public List<String> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
final ArrayList<String> result = new ArrayList<String>(l.size()); final ArrayList<String> result = new ArrayList<String>(l.size());
for (final byte[] barray : l) { for (final byte[] barray : l) {
if (barray == null) { if (barray == null) {
result.add(null); result.add(null);
} else { } else {
result.add(SafeEncoder.encode(barray)); result.add(SafeEncoder.encode(barray));
} }
} }
return result; return result;
} }
public String toString() { public String toString() {
return "List<String>"; return "List<String>";
} }
}; };
public static final Builder<Map<String, String>> STRING_MAP = new Builder<Map<String, String>>() { public static final Builder<Map<String, String>> STRING_MAP = new Builder<Map<String, String>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Map<String, String> build(Object data) { public Map<String, String> build(Object data) {
final List<byte[]> flatHash = (List<byte[]>) data; final List<byte[]> flatHash = (List<byte[]>) data;
final Map<String, String> hash = new HashMap<String, String>(); final Map<String, String> hash = new HashMap<String, String>();
final Iterator<byte[]> iterator = flatHash.iterator(); final Iterator<byte[]> iterator = flatHash.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
hash.put(SafeEncoder.encode(iterator.next()), SafeEncoder hash.put(SafeEncoder.encode(iterator.next()),
.encode(iterator.next())); SafeEncoder.encode(iterator.next()));
} }
return hash; return hash;
} }
public String toString() { public String toString() {
return "Map<String, String>"; return "Map<String, String>";
} }
}; };
public static final Builder<Set<String>> STRING_SET = new Builder<Set<String>>() {
@SuppressWarnings("unchecked")
public Set<String> build(Object data) {
if (null == data) {
return null;
}
List<byte[]> l = (List<byte[]>) data;
final Set<String> result = new HashSet<String>(l.size());
for (final byte[] barray : l) {
if (barray == null) {
result.add(null);
} else {
result.add(SafeEncoder.encode(barray));
}
}
return result;
}
public String toString() { public static final Builder<Set<String>> STRING_SET = new Builder<Set<String>>() {
return "Set<String>"; @SuppressWarnings("unchecked")
} public Set<String> build(Object data) {
if (null == data) {
return null;
}
List<byte[]> l = (List<byte[]>) data;
final Set<String> result = new HashSet<String>(l.size());
for (final byte[] barray : l) {
if (barray == null) {
result.add(null);
} else {
result.add(SafeEncoder.encode(barray));
}
}
return result;
}
public String toString() {
return "Set<String>";
}
}; };
public static final Builder<List<byte[]>> BYTE_ARRAY_LIST = new Builder<List<byte[]>>() { public static final Builder<List<byte[]>> BYTE_ARRAY_LIST = new Builder<List<byte[]>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<byte[]> build(Object data) { public List<byte[]> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
return l; return l;
} }
public String toString() { public String toString() {
return "List<byte[]>"; return "List<byte[]>";
} }
}; };
public static final Builder<Set<byte[]>> BYTE_ARRAY_ZSET = new Builder<Set<byte[]>>() { public static final Builder<Set<byte[]>> BYTE_ARRAY_ZSET = new Builder<Set<byte[]>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<byte[]> build(Object data) { public Set<byte[]> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
final Set<byte[]> result = new LinkedHashSet<byte[]>(l); final Set<byte[]> result = new LinkedHashSet<byte[]>(l);
for (final byte[] barray : l) { for (final byte[] barray : l) {
if (barray == null) { if (barray == null) {
result.add(null); result.add(null);
} else { } else {
result.add(barray); result.add(barray);
} }
} }
return result; return result;
} }
public String toString() { public String toString() {
return "ZSet<byte[]>"; return "ZSet<byte[]>";
} }
}; };
public static final Builder<Map<byte[], byte[]>> BYTE_ARRAY_MAP = new Builder<Map<byte[], byte[]>>() { public static final Builder<Map<byte[], byte[]>> BYTE_ARRAY_MAP = new Builder<Map<byte[], byte[]>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Map<byte[], byte[]> build(Object data) { public Map<byte[], byte[]> build(Object data) {
final List<byte[]> flatHash = (List<byte[]>) data; final List<byte[]> flatHash = (List<byte[]>) data;
final Map<byte[], byte[]> hash = new HashMap<byte[], byte[]>(); final Map<byte[], byte[]> hash = new HashMap<byte[], byte[]>();
final Iterator<byte[]> iterator = flatHash.iterator(); final Iterator<byte[]> iterator = flatHash.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
hash.put(iterator.next(), iterator.next()); hash.put(iterator.next(), iterator.next());
} }
return hash; return hash;
} }
public String toString() { public String toString() {
return "Map<byte[], byte[]>"; return "Map<byte[], byte[]>";
} }
}; };
public static final Builder<Set<String>> STRING_ZSET = new Builder<Set<String>>() { public static final Builder<Set<String>> STRING_ZSET = new Builder<Set<String>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<String> build(Object data) { public Set<String> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
final Set<String> result = new LinkedHashSet<String>(l.size()); final Set<String> result = new LinkedHashSet<String>(l.size());
for (final byte[] barray : l) { for (final byte[] barray : l) {
if (barray == null) { if (barray == null) {
result.add(null); result.add(null);
} else { } else {
result.add(SafeEncoder.encode(barray)); result.add(SafeEncoder.encode(barray));
} }
} }
return result; return result;
} }
public String toString() { public String toString() {
return "ZSet<String>"; return "ZSet<String>";
} }
}; };
public static final Builder<Set<Tuple>> TUPLE_ZSET = new Builder<Set<Tuple>>() { public static final Builder<Set<Tuple>> TUPLE_ZSET = new Builder<Set<Tuple>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<Tuple> build(Object data) { public Set<Tuple> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size()); final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size());
Iterator<byte[]> iterator = l.iterator(); Iterator<byte[]> iterator = l.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
result.add(new Tuple(SafeEncoder.encode(iterator.next()), result.add(new Tuple(SafeEncoder.encode(iterator.next()),
Double.valueOf(SafeEncoder.encode(iterator.next())))); Double.valueOf(SafeEncoder.encode(iterator.next()))));
} }
return result; return result;
} }
public String toString() { public String toString() {
return "ZSet<Tuple>"; return "ZSet<Tuple>";
} }
}; };
public static final Builder<Set<Tuple>> TUPLE_ZSET_BINARY = new Builder<Set<Tuple>>() { public static final Builder<Set<Tuple>> TUPLE_ZSET_BINARY = new Builder<Set<Tuple>>() {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public Set<Tuple> build(Object data) { public Set<Tuple> build(Object data) {
if (null == data) { if (null == data) {
return null; return null;
} }
List<byte[]> l = (List<byte[]>) data; List<byte[]> l = (List<byte[]>) data;
final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size()); final Set<Tuple> result = new LinkedHashSet<Tuple>(l.size());
Iterator<byte[]> iterator = l.iterator(); Iterator<byte[]> iterator = l.iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
result.add(new Tuple(iterator.next(), Double result.add(new Tuple(iterator.next(), Double
.valueOf(SafeEncoder.encode(iterator.next())))); .valueOf(SafeEncoder.encode(iterator.next()))));
} }
return result; return result;
} }
public String toString() { public String toString() {
return "ZSet<Tuple>"; return "ZSet<Tuple>";
} }
}; };
} }

View File

@@ -1,6 +1,6 @@
package redis.clients.jedis; package redis.clients.jedis;
import redis.clients.util.SafeEncoder; import static redis.clients.jedis.Protocol.toByteArray;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.HashMap; import java.util.HashMap;
@@ -8,8 +8,7 @@ import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Map.Entry; import java.util.Map.Entry;
import static redis.clients.jedis.Protocol.toByteArray; import redis.clients.util.SafeEncoder;
import static redis.clients.jedis.Protocol.Command.HSCAN;
public class Client extends BinaryClient implements Commands { public class Client extends BinaryClient implements Commands {
public Client(final String host) { public Client(final String host) {
@@ -24,8 +23,10 @@ public class Client extends BinaryClient implements Commands {
set(SafeEncoder.encode(key), SafeEncoder.encode(value)); set(SafeEncoder.encode(key), SafeEncoder.encode(value));
} }
public void set(final String key, final String value, final String nxxx, final String expx, final long time) { public void set(final String key, final String value, final String nxxx,
set(SafeEncoder.encode(key), SafeEncoder.encode(value), SafeEncoder.encode(nxxx), SafeEncoder.encode(expx), time); final String expx, final long time) {
set(SafeEncoder.encode(key), SafeEncoder.encode(value),
SafeEncoder.encode(nxxx), SafeEncoder.encode(expx), time);
} }
public void get(final String key) { public void get(final String key) {
@@ -394,12 +395,12 @@ public class Client extends BinaryClient implements Commands {
} }
public void blpop(final int timeout, final String... keys) { public void blpop(final int timeout, final String... keys) {
List<String> args = new ArrayList<String>(); List<String> args = new ArrayList<String>();
for (String arg : keys) { for (String arg : keys) {
args.add(arg); args.add(arg);
} }
args.add(String.valueOf(timeout)); args.add(String.valueOf(timeout));
blpop(args.toArray(new String[args.size()])); blpop(args.toArray(new String[args.size()]));
} }
public void sort(final String key, final SortingParams sortingParameters, public void sort(final String key, final SortingParams sortingParameters,
@@ -421,12 +422,12 @@ public class Client extends BinaryClient implements Commands {
} }
public void brpop(final int timeout, final String... keys) { public void brpop(final int timeout, final String... keys) {
List<String> args = new ArrayList<String>(); List<String> args = new ArrayList<String>();
for (String arg : keys) { for (String arg : keys) {
args.add(arg); args.add(arg);
} }
args.add(String.valueOf(timeout)); args.add(String.valueOf(timeout));
brpop(args.toArray(new String[args.size()])); brpop(args.toArray(new String[args.size()]));
} }
public void zcount(final String key, final double min, final double max) { public void zcount(final String key, final double min, final double max) {
@@ -621,13 +622,16 @@ public class Client extends BinaryClient implements Commands {
} }
public void setbit(final String key, final long offset, final String value) { public void setbit(final String key, final long offset, final String value) {
setbit(SafeEncoder.encode(key), offset, SafeEncoder.encode(value)); setbit(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));
} }
public void getbit(String key, long offset) { public void getbit(String key, long offset) {
getbit(SafeEncoder.encode(key), offset); getbit(SafeEncoder.encode(key), offset);
} }
public void bitpos(final String key, final boolean value, final BitPosParams params) {
bitpos(SafeEncoder.encode(key), value, params);
}
public void setrange(String key, long offset, String value) { public void setrange(String key, long offset, String value) {
setrange(SafeEncoder.encode(key), offset, SafeEncoder.encode(value)); setrange(SafeEncoder.encode(key), offset, SafeEncoder.encode(value));
} }
@@ -672,6 +676,18 @@ public class Client extends BinaryClient implements Commands {
subscribe(cs); subscribe(cs);
} }
public void pubsubChannels(String pattern) {
pubsub(Protocol.PUBSUB_CHANNELS, pattern);
}
public void pubsubNumPat() {
pubsub(Protocol.PUBSUB_NUM_PAT);
}
public void pubsubNumSub(String... channels) {
pubsub(Protocol.PUBSUB_NUMSUB, channels);
}
public void configSet(String parameter, String value) { public void configSet(String parameter, String value) {
configSet(SafeEncoder.encode(parameter), SafeEncoder.encode(value)); configSet(SafeEncoder.encode(parameter), SafeEncoder.encode(value));
} }
@@ -710,12 +726,14 @@ public class Client extends BinaryClient implements Commands {
scriptLoad(SafeEncoder.encode(script)); scriptLoad(SafeEncoder.encode(script));
} }
public void zadd(String key, Map<Double, String> scoreMembers) { public void zadd(String key, Map<String, Double> scoreMembers) {
HashMap<Double, byte[]> binaryScoreMembers = new HashMap<Double, byte[]>();
for (Map.Entry<Double, String> entry : scoreMembers.entrySet()) { HashMap<byte[], Double> binaryScoreMembers = new HashMap<byte[], Double>();
binaryScoreMembers.put(entry.getKey(),
SafeEncoder.encode(entry.getValue())); for (Map.Entry<String, Double> entry : scoreMembers.entrySet()) {
binaryScoreMembers.put(SafeEncoder.encode(entry.getKey()),
entry.getValue());
} }
zaddBinary(SafeEncoder.encode(key), binaryScoreMembers); zaddBinary(SafeEncoder.encode(key), binaryScoreMembers);
@@ -734,15 +752,15 @@ public class Client extends BinaryClient implements Commands {
} }
public void bitcount(final String key) { public void bitcount(final String key) {
bitcount(SafeEncoder.encode(key)); bitcount(SafeEncoder.encode(key));
} }
public void bitcount(final String key, long start, long end) { public void bitcount(final String key, long start, long end) {
bitcount(SafeEncoder.encode(key), start, end); bitcount(SafeEncoder.encode(key), start, end);
} }
public void bitop(BitOP op, final String destKey, String... srcKeys) { public void bitop(BitOP op, final String destKey, String... srcKeys) {
bitop(op, SafeEncoder.encode(destKey), getByteParams(srcKeys)); bitop(op, SafeEncoder.encode(destKey), getByteParams(srcKeys));
} }
public void sentinel(final String... args) { public void sentinel(final String... args) {
@@ -754,86 +772,143 @@ public class Client extends BinaryClient implements Commands {
} }
public void dump(final String key) { public void dump(final String key) {
dump(SafeEncoder.encode(key)); dump(SafeEncoder.encode(key));
} }
public void restore(final String key, final int ttl, final byte[] serializedValue) { public void restore(final String key, final int ttl,
restore(SafeEncoder.encode(key), ttl, serializedValue); final byte[] serializedValue) {
restore(SafeEncoder.encode(key), ttl, serializedValue);
} }
@Deprecated
public void pexpire(final String key, final int milliseconds) { public void pexpire(final String key, final int milliseconds) {
pexpire(SafeEncoder.encode(key), milliseconds); pexpire(key, (long) milliseconds);
}
public void pexpire(final String key, final long milliseconds) {
pexpire(SafeEncoder.encode(key), milliseconds);
} }
public void pexpireAt(final String key, final long millisecondsTimestamp) { public void pexpireAt(final String key, final long millisecondsTimestamp) {
pexpireAt(SafeEncoder.encode(key), millisecondsTimestamp); pexpireAt(SafeEncoder.encode(key), millisecondsTimestamp);
} }
public void pttl(final String key) { public void pttl(final String key) {
pttl(SafeEncoder.encode(key)); pttl(SafeEncoder.encode(key));
} }
public void incrByFloat(final String key, final double increment) { public void incrByFloat(final String key, final double increment) {
incrByFloat(SafeEncoder.encode(key), increment); incrByFloat(SafeEncoder.encode(key), increment);
} }
public void psetex(final String key, final int milliseconds, final String value) { public void psetex(final String key, final int milliseconds,
psetex(SafeEncoder.encode(key), milliseconds, SafeEncoder.encode(value)); final String value) {
psetex(SafeEncoder.encode(key), milliseconds, SafeEncoder.encode(value));
} }
public void set(final String key, final String value, final String nxxx) { public void set(final String key, final String value, final String nxxx) {
set(SafeEncoder.encode(key), SafeEncoder.encode(value), SafeEncoder.encode(nxxx)); set(SafeEncoder.encode(key), SafeEncoder.encode(value),
SafeEncoder.encode(nxxx));
} }
public void set(final String key, final String value, final String nxxx, final String expx, final int time) { public void set(final String key, final String value, final String nxxx,
set(SafeEncoder.encode(key), SafeEncoder.encode(value), SafeEncoder.encode(nxxx), SafeEncoder.encode(expx), time); final String expx, final int time) {
set(SafeEncoder.encode(key), SafeEncoder.encode(value),
SafeEncoder.encode(nxxx), SafeEncoder.encode(expx), time);
} }
public void srandmember(final String key, final int count) { public void srandmember(final String key, final int count) {
srandmember(SafeEncoder.encode(key), count); srandmember(SafeEncoder.encode(key), count);
} }
public void clientKill(final String client) { public void clientKill(final String client) {
clientKill(SafeEncoder.encode(client)); clientKill(SafeEncoder.encode(client));
} }
public void clientSetname(final String name) { public void clientSetname(final String name) {
clientSetname(SafeEncoder.encode(name)); clientSetname(SafeEncoder.encode(name));
} }
public void migrate(final String host, final int port, final String key, final int destinationDb, final int timeout) { public void migrate(final String host, final int port, final String key,
migrate(SafeEncoder.encode(host), port, SafeEncoder.encode(key), destinationDb, timeout); final int destinationDb, final int timeout) {
migrate(SafeEncoder.encode(host), port, SafeEncoder.encode(key),
destinationDb, timeout);
} }
public void hincrByFloat(final String key, final String field, double increment) { public void hincrByFloat(final String key, final String field,
hincrByFloat(SafeEncoder.encode(key), SafeEncoder.encode(field), increment); double increment) {
hincrByFloat(SafeEncoder.encode(key), SafeEncoder.encode(field),
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) { public void hscan(final String key, int cursor, final ScanParams params) {
hscan(SafeEncoder.encode(key), cursor, 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) { public void sscan(final String key, int cursor, final ScanParams params) {
sscan(SafeEncoder.encode(key), cursor, 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) { public void zscan(final String key, int cursor, final ScanParams params) {
zscan(SafeEncoder.encode(key), cursor, params); zscan(SafeEncoder.encode(key), cursor, params);
}
public void scan(final String cursor, final ScanParams params) {
scan(SafeEncoder.encode(cursor), params);
}
public void hscan(final String key, final String cursor, final ScanParams params) {
hscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);
}
public void sscan(final String key, final String cursor, final ScanParams params) {
sscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);
}
public void zscan(final String key, final String cursor, final ScanParams params) {
zscan(SafeEncoder.encode(key), SafeEncoder.encode(cursor), params);
} }
public void cluster(final String subcommand, final int... args) { public void cluster(final String subcommand, final int... args) {
final byte[][] arg = new byte[args.length+1][]; final byte[][] arg = new byte[args.length + 1][];
for (int i = 1; i < arg.length; i++) { for (int i = 1; i < arg.length; i++) {
arg[i] = toByteArray(args[i-1]); arg[i] = toByteArray(args[i - 1]);
} }
arg[0] = SafeEncoder.encode(subcommand); arg[0] = SafeEncoder.encode(subcommand);
cluster(arg); cluster(arg);
} }
public void pubsub(final String subcommand, final String... args) {
final byte[][] arg = new byte[args.length+1][];
for (int i = 1; i < arg.length; i++) {
arg[i] = SafeEncoder.encode(args[i-1]);
}
arg[0] = SafeEncoder.encode(subcommand);
pubsub(arg);
}
public void cluster(final String subcommand, final String... args) { public void cluster(final String subcommand, final String... args) {
final byte[][] arg = new byte[args.length+1][]; final byte[][] arg = new byte[args.length + 1][];
for (int i = 1; i < arg.length; i++) { for (int i = 1; i < arg.length; i++) {
arg[i] = SafeEncoder.encode(args[i-1]); arg[i] = SafeEncoder.encode(args[i - 1]);
} }
arg[0] = SafeEncoder.encode(subcommand); arg[0] = SafeEncoder.encode(subcommand);
cluster(arg); cluster(arg);
@@ -853,11 +928,11 @@ public class Client extends BinaryClient implements Commands {
cluster(Protocol.CLUSTER_MEET, ip, String.valueOf(port)); cluster(Protocol.CLUSTER_MEET, ip, String.valueOf(port));
} }
public void clusterAddSlots(final int ...slots) { public void clusterAddSlots(final int... slots) {
cluster(Protocol.CLUSTER_ADDSLOTS, slots); cluster(Protocol.CLUSTER_ADDSLOTS, slots);
} }
public void clusterDelSlots(final int ...slots) { public void clusterDelSlots(final int... slots) {
cluster(Protocol.CLUSTER_DELSLOTS, slots); cluster(Protocol.CLUSTER_DELSLOTS, slots);
} }
@@ -866,19 +941,74 @@ public class Client extends BinaryClient implements Commands {
} }
public void clusterGetKeysInSlot(final int slot, final int count) { public void clusterGetKeysInSlot(final int slot, final int count) {
final int[] args = new int[]{ slot, count }; final int[] args = new int[] { slot, count };
cluster(Protocol.CLUSTER_GETKEYSINSLOT, args); cluster(Protocol.CLUSTER_GETKEYSINSLOT, args);
} }
public void clusterSetSlotNode(final int slot, final String nodeId) { public void clusterSetSlotNode(final int slot, final String nodeId) {
cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_NODE, nodeId); cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot),
Protocol.CLUSTER_SETSLOT_NODE, nodeId);
} }
public void clusterSetSlotMigrating(final int slot, final String nodeId) { public void clusterSetSlotMigrating(final int slot, final String nodeId) {
cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_MIGRATING, nodeId); cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot),
Protocol.CLUSTER_SETSLOT_MIGRATING, nodeId);
} }
public void clusterSetSlotImporting(final int slot, final String nodeId) { public void clusterSetSlotImporting(final int slot, final String nodeId) {
cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot), Protocol.CLUSTER_SETSLOT_IMPORTING, nodeId); cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot),
Protocol.CLUSTER_SETSLOT_IMPORTING, nodeId);
}
public void pfadd(String key, final String... elements) {
pfadd(SafeEncoder.encode(key), SafeEncoder.encodeMany(elements));
}
public void pfcount(final String key) {
pfcount(SafeEncoder.encode(key));
}
public void pfcount(final String...keys) {
pfcount(SafeEncoder.encodeMany(keys));
}
public void pfmerge(final String destkey, final String... sourcekeys) {
pfmerge(SafeEncoder.encode(destkey), SafeEncoder.encodeMany(sourcekeys));
}
public void clusterSetSlotStable(final int slot) {
cluster(Protocol.CLUSTER_SETSLOT, String.valueOf(slot),
Protocol.CLUSTER_SETSLOT_STABLE);
}
public void clusterForget(final String nodeId) {
cluster(Protocol.CLUSTER_FORGET, nodeId);
}
public void clusterFlushSlots() {
cluster(Protocol.CLUSTER_FLUSHSLOT);
}
public void clusterKeySlot(final String key) {
cluster(Protocol.CLUSTER_KEYSLOT, key);
}
public void clusterCountKeysInSlot(final int slot) {
cluster(Protocol.CLUSTER_COUNTKEYINSLOT, String.valueOf(slot));
}
public void clusterSaveConfig() {
cluster(Protocol.CLUSTER_SAVECONFIG);
}
public void clusterReplicate(final String nodeId) {
cluster(Protocol.CLUSTER_REPLICATE, nodeId);
}
public void clusterSlaves(final String nodeId) {
cluster(Protocol.CLUSTER_SLAVES, nodeId);
}
public void clusterFailover() {
cluster(Protocol.CLUSTER_FAILOVER);
} }
} }

View File

@@ -20,4 +20,22 @@ public interface ClusterCommands {
String clusterSetSlotMigrating(final int slot, final String nodeId); String clusterSetSlotMigrating(final int slot, final String nodeId);
String clusterSetSlotImporting(final int slot, final String nodeId); String clusterSetSlotImporting(final int slot, final String nodeId);
String clusterSetSlotStable(final int slot);
String clusterForget(final String nodeId);
String clusterFlushSlots();
Long clusterKeySlot(final String key);
Long clusterCountKeysInSlot(final int slot);
String clusterSaveConfig();
String clusterReplicate(final String nodeId);
List<String> clusterSlaves(final String nodeId);
String clusterFailover();
} }

View File

@@ -61,6 +61,8 @@ public interface Commands {
public void incrBy(final String key, final long integer); public void incrBy(final String key, final long integer);
public void incrByFloat(final String key, final double value);
public void incr(final String key); public void incr(final String key);
public void append(final String key, final String value); public void append(final String key, final String value);
@@ -79,6 +81,8 @@ public interface Commands {
public void hincrBy(final String key, final String field, final long value); public void hincrBy(final String key, final String field, final long value);
public void hincrByFloat(final String key, final String field, final double value);
public void hexists(final String key, final String field); public void hexists(final String key, final String field);
public void hdel(final String key, final String... fields); public void hdel(final String key, final String... fields);
@@ -144,7 +148,7 @@ public interface Commands {
public void zadd(final String key, final double score, final String member); public void zadd(final String key, final double score, final String member);
public void zadd(final String key, final Map<Double, String> scoreMembers); public void zadd(final String key, final Map<String, Double> scoreMembers);
public void zrange(final String key, final long start, final long end); public void zrange(final String key, final long start, final long end);
@@ -297,13 +301,45 @@ public interface Commands {
public void bitop(BitOP op, final String destKey, String... srcKeys); 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); 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); 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); 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 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);
public void sscan(final String key, final String cursor, final ScanParams params);
public void zscan(final String key, final String cursor, final ScanParams params);
public void waitReplicas(int replicas, long timeout); public void waitReplicas(int replicas, long timeout);
} }

View File

@@ -1,5 +1,6 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.io.Closeable;
import java.io.IOException; import java.io.IOException;
import java.net.InetSocketAddress; import java.net.InetSocketAddress;
import java.net.Socket; import java.net.Socket;
@@ -10,12 +11,11 @@ import java.util.List;
import redis.clients.jedis.Protocol.Command; import redis.clients.jedis.Protocol.Command;
import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.util.RedisInputStream; import redis.clients.util.RedisInputStream;
import redis.clients.util.RedisOutputStream; import redis.clients.util.RedisOutputStream;
import redis.clients.util.SafeEncoder; import redis.clients.util.SafeEncoder;
public class Connection { public class Connection implements Closeable {
private String host; private String host;
private int port = Protocol.DEFAULT_PORT; private int port = Protocol.DEFAULT_PORT;
private Socket socket; private Socket socket;
@@ -23,92 +23,100 @@ public class Connection {
private RedisInputStream inputStream; private RedisInputStream inputStream;
private int timeout = Protocol.DEFAULT_TIMEOUT; private int timeout = Protocol.DEFAULT_TIMEOUT;
private boolean broken = false;
public Socket getSocket() { public Socket getSocket() {
return socket; return socket;
} }
public int getTimeout() { public int getTimeout() {
return timeout; return timeout;
} }
public void setTimeout(final int timeout) { public void setTimeout(final int timeout) {
this.timeout = timeout; this.timeout = timeout;
} }
public void setTimeoutInfinite() { public void setTimeoutInfinite() {
try { try {
if(!isConnected()) { if (!isConnected()) {
connect(); connect();
} }
socket.setKeepAlive(true); socket.setKeepAlive(true);
socket.setSoTimeout(0); socket.setSoTimeout(0);
} catch (SocketException ex) { } catch (SocketException ex) {
throw new JedisException(ex); broken = true;
} throw new JedisConnectionException(ex);
}
} }
public void rollbackTimeout() { public void rollbackTimeout() {
try { try {
socket.setSoTimeout(timeout); socket.setSoTimeout(timeout);
socket.setKeepAlive(false); socket.setKeepAlive(false);
} catch (SocketException ex) { } catch (SocketException ex) {
throw new JedisException(ex); broken = true;
} throw new JedisConnectionException(ex);
}
} }
public Connection(final String host) { public Connection(final String host) {
super(); super();
this.host = host; this.host = host;
}
protected void flush() {
try {
outputStream.flush();
} catch (IOException e) {
throw new JedisConnectionException(e);
}
} }
protected Connection sendCommand(final Command cmd, final String... args) { protected Connection sendCommand(final Command cmd, final String... args) {
final byte[][] bargs = new byte[args.length][]; final byte[][] bargs = new byte[args.length][];
for (int i = 0; i < args.length; i++) { for (int i = 0; i < args.length; i++) {
bargs[i] = SafeEncoder.encode(args[i]); bargs[i] = SafeEncoder.encode(args[i]);
} }
return sendCommand(cmd, bargs); return sendCommand(cmd, bargs);
} }
protected Connection sendCommand(final Command cmd, final byte[]... args) { protected Connection sendCommand(final Command cmd, final byte[]... args) {
connect(); try {
Protocol.sendCommand(outputStream, cmd, args); connect();
return this; Protocol.sendCommand(outputStream, cmd, args);
return this;
} catch (JedisConnectionException ex) {
// Any other exceptions related to connection?
broken = true;
throw ex;
}
} }
protected Connection sendCommand(final Command cmd) { protected Connection sendCommand(final Command cmd) {
connect(); try {
Protocol.sendCommand(outputStream, cmd, new byte[0][]); connect();
return this; Protocol.sendCommand(outputStream, cmd, new byte[0][]);
return this;
} catch (JedisConnectionException ex) {
// Any other exceptions related to connection?
broken = true;
throw ex;
}
} }
public Connection(final String host, final int port) { public Connection(final String host, final int port) {
super(); super();
this.host = host; this.host = host;
this.port = port; this.port = port;
} }
public String getHost() { public String getHost() {
return host; return host;
} }
public void setHost(final String host) { public void setHost(final String host) {
this.host = host; this.host = host;
} }
public int getPort() { public int getPort() {
return port; return port;
} }
public void setPort(final int port) { public void setPort(final int port) {
this.port = port; this.port = port;
} }
public Connection() { public Connection() {
@@ -116,89 +124,104 @@ public class Connection {
} }
public void connect() { public void connect() {
if (!isConnected()) { if (!isConnected()) {
try { try {
socket = new Socket(); socket = new Socket();
//->@wjw_add // ->@wjw_add
socket.setReuseAddress(true); socket.setReuseAddress(true);
socket.setKeepAlive(true); //Will monitor the TCP connection is valid socket.setKeepAlive(true); // Will monitor the TCP connection is
socket.setTcpNoDelay(true); //Socket buffer Whetherclosed, to ensure timely delivery of data // valid
socket.setSoLinger(true,0); //Control calls close () method, the underlying socket is closed immediately socket.setTcpNoDelay(true); // Socket buffer Whetherclosed, to
//<-@wjw_add // ensure timely delivery of data
socket.setSoLinger(true, 0); // Control calls close () method,
// the underlying socket is closed
// immediately
// <-@wjw_add
socket.connect(new InetSocketAddress(host, port), timeout); socket.connect(new InetSocketAddress(host, port), timeout);
socket.setSoTimeout(timeout); socket.setSoTimeout(timeout);
outputStream = new RedisOutputStream(socket.getOutputStream()); outputStream = new RedisOutputStream(socket.getOutputStream());
inputStream = new RedisInputStream(socket.getInputStream()); inputStream = new RedisInputStream(socket.getInputStream());
} catch (IOException ex) { } catch (IOException ex) {
throw new JedisConnectionException(ex); broken = true;
} throw new JedisConnectionException(ex);
} }
}
}
@Override
public void close() {
disconnect();
} }
public void disconnect() { public void disconnect() {
if (isConnected()) { if (isConnected()) {
try { try {
inputStream.close(); inputStream.close();
outputStream.close(); outputStream.close();
if (!socket.isClosed()) { if (!socket.isClosed()) {
socket.close(); socket.close();
} }
} catch (IOException ex) { } catch (IOException ex) {
throw new JedisConnectionException(ex); broken = true;
} throw new JedisConnectionException(ex);
} }
}
} }
public boolean isConnected() { public boolean isConnected() {
return socket != null && socket.isBound() && !socket.isClosed() return socket != null && socket.isBound() && !socket.isClosed()
&& socket.isConnected() && !socket.isInputShutdown() && socket.isConnected() && !socket.isInputShutdown()
&& !socket.isOutputShutdown(); && !socket.isOutputShutdown();
} }
protected String getStatusCodeReply() { protected String getStatusCodeReply() {
flush(); flush();
final byte[] resp = (byte[]) Protocol.read(inputStream); final byte[] resp = (byte[]) readProtocolWithCheckingBroken();
if (null == resp) { if (null == resp) {
return null; return null;
} else { } else {
return SafeEncoder.encode(resp); return SafeEncoder.encode(resp);
} }
} }
public String getBulkReply() { public String getBulkReply() {
final byte[] result = getBinaryBulkReply(); final byte[] result = getBinaryBulkReply();
if (null != result) { if (null != result) {
return SafeEncoder.encode(result); return SafeEncoder.encode(result);
} else { } else {
return null; return null;
} }
} }
public byte[] getBinaryBulkReply() { public byte[] getBinaryBulkReply() {
flush(); flush();
return (byte[]) Protocol.read(inputStream); return (byte[]) readProtocolWithCheckingBroken();
} }
public Long getIntegerReply() { public Long getIntegerReply() {
flush(); flush();
return (Long) Protocol.read(inputStream); return (Long) readProtocolWithCheckingBroken();
} }
public List<String> getMultiBulkReply() { public List<String> getMultiBulkReply() {
return BuilderFactory.STRING_LIST.build(getBinaryMultiBulkReply()); return BuilderFactory.STRING_LIST.build(getBinaryMultiBulkReply());
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<byte[]> getBinaryMultiBulkReply() { public List<byte[]> getBinaryMultiBulkReply() {
flush(); flush();
return (List<byte[]>) Protocol.read(inputStream); return (List<byte[]>) readProtocolWithCheckingBroken();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public List<Object> getRawObjectMultiBulkReply() {
return (List<Object>) readProtocolWithCheckingBroken();
}
public List<Object> getObjectMultiBulkReply() { public List<Object> getObjectMultiBulkReply() {
flush(); flush();
return (List<Object>) Protocol.read(inputStream); return getRawObjectMultiBulkReply();
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@@ -209,7 +232,29 @@ public class Connection {
public Object getOne() { public Object getOne() {
flush(); flush();
return Protocol.read(inputStream); return readProtocolWithCheckingBroken();
}
public boolean isBroken() {
return broken;
}
protected void flush() {
try {
outputStream.flush();
} catch (IOException ex) {
broken = true;
throw new JedisConnectionException(ex);
}
}
protected Object readProtocolWithCheckingBroken() {
try {
return Protocol.read(inputStream);
} catch (JedisConnectionException exc) {
broken = true;
throw exc;
}
} }
public List<Object> getMany(int count) { public List<Object> getMany(int count) {
@@ -217,7 +262,7 @@ public class Connection {
List<Object> responses = new ArrayList<Object>(); List<Object> responses = new ArrayList<Object>();
for (int i = 0 ; i < count ; i++) { for (int i = 0 ; i < count ; i++) {
try { try {
responses.add(Protocol.read(inputStream)); responses.add(readProtocolWithCheckingBroken());
} catch (JedisDataException e) { } catch (JedisDataException e) {
responses.add(e); responses.add(e);
} }

View File

@@ -1,50 +1,49 @@
package redis.clients.jedis; package redis.clients.jedis;
public class HostAndPort { public class HostAndPort {
public static final String LOCALHOST_STR = "localhost"; public static final String LOCALHOST_STR = "localhost";
private String host; private String host;
private int port; private int port;
public HostAndPort(String host, int port) {
this.host = host;
this.port = port;
}
public String getHost() {
return host;
}
public int getPort() {
return port;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof HostAndPort) {
HostAndPort hp = (HostAndPort) obj;
String thisHost = convertHost(host);
String hpHost = convertHost(hp.host);
return port == hp.port && thisHost.equals(hpHost);
public HostAndPort(String host, int port) {
this.host = host;
this.port = port;
} }
public String getHost() { return false;
return host; }
}
public int getPort() { @Override
return port; public String toString() {
} return host + ":" + port;
}
@Override
public boolean equals(Object obj) {
if (obj instanceof HostAndPort) {
HostAndPort hp = (HostAndPort) obj;
String thisHost = convertHost(host);
String hpHost = convertHost(hp.host);
return port == hp.port &&
thisHost.equals(hpHost);
}
return false;
}
@Override
public String toString() {
return host + ":" + port;
}
private String convertHost(String host) { private String convertHost(String host) {
if (host.equals("127.0.0.1")) if (host.equals("127.0.0.1"))
return LOCALHOST_STR; return LOCALHOST_STR;
else if (host.equals("::1")) else if (host.equals("::1"))
return LOCALHOST_STR; return LOCALHOST_STR;
return host; return host;
} }
} }

View File

@@ -1,22 +1,20 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.net.URI;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Set;
import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.util.Pool;
import redis.clients.util.SafeEncoder; import redis.clients.util.SafeEncoder;
import redis.clients.util.Slowlog; import redis.clients.util.Slowlog;
import java.net.URI; import java.net.URI;
import java.util.*; import java.util.*;
import java.util.Map.Entry;
public class Jedis extends BinaryJedis implements JedisCommands,
MultiKeyCommands, AdvancedJedisCommands, ScriptingCommands,
BasicCommands, ClusterCommands {
protected Pool<Jedis> dataSource = null;
public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommands, AdvancedJedisCommands, ScriptingCommands, BasicCommands, ClusterCommands {
public Jedis(final String host) { public Jedis(final String host) {
super(host); super(host);
} }
@@ -56,24 +54,29 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
/** /**
* Set the string value as value of the key. The string can't be longer than * Set the string value as value of the key. The string can't be longer than
* 1073741824 bytes (1 GB). * 1073741824 bytes (1 GB).
*
* @param key * @param key
* @param value * @param value
* @param nxxx NX|XX, NX -- Only set the key if it does not already exist. * @param nxxx
* XX -- Only set the key if it already exist. * NX|XX, NX -- Only set the key if it does not already exist. XX
* @param expx EX|PX, expire time units: EX = seconds; PX = milliseconds * -- Only set the key if it already exist.
* @param time expire time in the units of {@param #expx} * @param expx
* EX|PX, expire time units: EX = seconds; PX = milliseconds
* @param time
* expire time in the units of {@param #expx}
* @return Status code reply * @return Status code reply
*/ */
public String set(final String key, final String value, final String nxxx, final String expx, final long time) { public String set(final String key, final String value, final String nxxx,
checkIsInMulti(); final String expx, final long time) {
client.set(key, value, nxxx, expx, time); checkIsInMulti();
return client.getStatusCodeReply(); client.set(key, value, nxxx, expx, time);
return client.getStatusCodeReply();
} }
/** /**
* Get the value of the specified key. If the key does not exist the special * Get the value of the specified key. If the key does not exist null is
* value 'nil' is returned. If the value stored at key is not a string an * returned. If the value stored at key is not a string an error is returned
* error is returned because GET can only handle string values. * because GET can only handle string values.
* <p> * <p>
* Time complexity: O(1) * Time complexity: O(1)
* *
@@ -119,8 +122,8 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
public Long del(String key) { public Long del(String key) {
client.del(key); client.del(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
/** /**
@@ -541,6 +544,31 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return client.getIntegerReply(); return client.getIntegerReply();
} }
/**
* INCRBYFLOAT
* <p>
* 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
* 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);
}
/** /**
* Increment the number stored at key by one. If the key does not exist or * Increment the number stored at key by one. If the key does not exist or
* contains a value of a wrong type, set the key to the value of "0" before * contains a value of a wrong type, set the key to the value of "0" before
@@ -733,6 +761,32 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return client.getIntegerReply(); return client.getIntegerReply();
} }
/**
* 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.
* <p>
* 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.
*/
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);
}
/** /**
* Test for existence of a specified field in a hash. * Test for existence of a specified field in a hash.
* *
@@ -1062,8 +1116,8 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
/** /**
* Atomically return and remove the first (LPOP) or last (RPOP) element of * 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 * the list. For example if the list contains the elements "a","b","c" RPOP
* will return "a" and the list will become "b","c". * will return "c" and the list will become "a","b".
* <p> * <p>
* If the key does not exist or the list is already empty the special value * If the key does not exist or the list is already empty the special value
* 'nil' is returned. * 'nil' is returned.
@@ -1415,7 +1469,7 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long zadd(final String key, final Map<Double, String> scoreMembers) { public Long zadd(final String key, final Map<String, Double> scoreMembers) {
checkIsInMulti(); checkIsInMulti();
client.zadd(key, scoreMembers); client.zadd(key, scoreMembers);
return client.getIntegerReply(); return client.getIntegerReply();
@@ -1789,39 +1843,39 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
public List<String> blpop(String... args) { public List<String> blpop(String... args) {
client.blpop(args); client.blpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<String> multiBulkReply = client.getMultiBulkReply(); final List<String> multiBulkReply = client.getMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<String> brpop(String... args) { public List<String> brpop(String... args) {
client.brpop(args); client.brpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<String> multiBulkReply = client.getMultiBulkReply(); final List<String> multiBulkReply = client.getMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<String> blpop(String arg) { public List<String> blpop(String arg) {
String[] args = new String[1]; String[] args = new String[1];
args[0] = arg; args[0] = arg;
client.blpop(args); client.blpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<String> multiBulkReply = client.getMultiBulkReply(); final List<String> multiBulkReply = client.getMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
public List<String> brpop(String arg) { public List<String> brpop(String arg) {
String[] args = new String[1]; String[] args = new String[1];
args[0] = arg; args[0] = arg;
client.brpop(args); client.brpop(args);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
final List<String> multiBulkReply = client.getMultiBulkReply(); final List<String> multiBulkReply = client.getMultiBulkReply();
client.rollbackTimeout(); client.rollbackTimeout();
return multiBulkReply; return multiBulkReply;
} }
/** /**
@@ -1954,8 +2008,6 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return multiBulkReply; return multiBulkReply;
} }
public Long zcount(final String key, final double min, final double max) { public Long zcount(final String key, final double min, final double max) {
checkIsInMulti(); checkIsInMulti();
client.zcount(key, min, max); client.zcount(key, min, max);
@@ -2020,8 +2072,10 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
* @see #zcount(String, double, double) * @see #zcount(String, double, double)
* *
* @param key * @param key
* @param min a double or Double.MIN_VALUE for "-inf" * @param min
* @param max a double or Double.MAX_VALUE for "+inf" * a double or Double.MIN_VALUE for "-inf"
* @param max
* a double or Double.MAX_VALUE for "+inf"
* @return Multi bulk reply specifically a list of elements in the specified * @return Multi bulk reply specifically a list of elements in the specified
* score range. * score range.
*/ */
@@ -2628,8 +2682,8 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
public Boolean setbit(String key, long offset, String value) { public Boolean setbit(String key, long offset, String value) {
client.setbit(key, offset, value); client.setbit(key, offset, value);
return client.getIntegerReply() == 1; return client.getIntegerReply() == 1;
} }
/** /**
@@ -2654,6 +2708,15 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return client.getBulkReply(); 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) {
client.bitpos(key, value, params);
return client.getIntegerReply();
}
/** /**
* Retrieve the configuration of a running Redis server. Not all the * Retrieve the configuration of a running Redis server. Not all the
* configuration parameters are supported. * configuration parameters are supported.
@@ -2742,26 +2805,26 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
public void subscribe(final JedisPubSub jedisPubSub, public void subscribe(final JedisPubSub jedisPubSub,
final String... channels) { final String... channels) {
client.setTimeoutInfinite(); client.setTimeoutInfinite();
jedisPubSub.proceed(client, channels); jedisPubSub.proceed(client, channels);
client.rollbackTimeout(); client.rollbackTimeout();
} }
public Long publish(final String channel, final String message) { public Long publish(final String channel, final String message) {
checkIsInMulti(); checkIsInMulti();
connect(); connect();
client.publish(channel, message); client.publish(channel, message);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public void psubscribe(final JedisPubSub jedisPubSub, public void psubscribe(final JedisPubSub jedisPubSub,
final String... patterns) { final String... patterns) {
checkIsInMulti(); checkIsInMulti();
connect(); connect();
client.setTimeoutInfinite(); client.setTimeoutInfinite();
jedisPubSub.proceedWithPatterns(client, patterns); jedisPubSub.proceedWithPatterns(client, patterns);
client.rollbackTimeout(); client.rollbackTimeout();
} }
protected static String[] getParams(List<String> keys, List<String> args) { protected static String[] getParams(List<String> keys, List<String> args) {
@@ -2792,17 +2855,18 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
private Object getEvalResult() { private Object getEvalResult() {
Object result = client.getOne(); return evalResult(client.getOne());
}
private Object evalResult(Object result) {
if (result instanceof byte[]) if (result instanceof byte[])
return SafeEncoder.encode((byte[]) result); return SafeEncoder.encode((byte[]) result);
if (result instanceof List<?>) { if (result instanceof List<?>) {
List<?> list = (List<?>) result; List<?> list = (List<?>) result;
List<String> listResult = new ArrayList<String>(list.size()); List<Object> listResult = new ArrayList<Object>(list.size());
for (Object bin : list) { for (Object bin : list) {
listResult.add((bin == null ? null : SafeEncoder listResult.add(evalResult(bin));
.encode((byte[]) bin)));
} }
return listResult; return listResult;
@@ -2870,18 +2934,18 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
} }
public Long bitcount(final String key) { public Long bitcount(final String key) {
client.bitcount(key); client.bitcount(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long bitcount(final String key, long start, long end) { public Long bitcount(final String key, long start, long end) {
client.bitcount(key, start, end); client.bitcount(key, start, end);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long bitop(BitOP op, final String destKey, String... srcKeys) { public Long bitop(BitOP op, final String destKey, String... srcKeys) {
client.bitop(op, destKey, srcKeys); client.bitop(op, destKey, srcKeys);
return client.getIntegerReply(); return client.getIntegerReply();
} }
/** /**
@@ -2917,7 +2981,7 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
* @return * @return
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public List<Map<String, String>> sentinelMasters() { public List<Map<String, String>> sentinelMasters() {
client.sentinel(Protocol.SENTINEL_MASTERS); client.sentinel(Protocol.SENTINEL_MASTERS);
final List<Object> reply = client.getObjectMultiBulkReply(); final List<Object> reply = client.getObjectMultiBulkReply();
@@ -2995,7 +3059,7 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
* @return * @return
*/ */
@SuppressWarnings("rawtypes") @SuppressWarnings("rawtypes")
public List<Map<String, String>> sentinelSlaves(String masterName) { public List<Map<String, String>> sentinelSlaves(String masterName) {
client.sentinel(Protocol.SENTINEL_SLAVES, masterName); client.sentinel(Protocol.SENTINEL_SLAVES, masterName);
final List<Object> reply = client.getObjectMultiBulkReply(); final List<Object> reply = client.getObjectMultiBulkReply();
@@ -3006,212 +3070,490 @@ public class Jedis extends BinaryJedis implements JedisCommands, MultiKeyCommand
return slaves; return slaves;
} }
public String sentinelFailover(String masterName) {
client.sentinel(Protocol.SENTINEL_FAILOVER, masterName);
return client.getStatusCodeReply();
}
public String sentinelMonitor(String masterName, String ip, int port,
int quorum) {
client.sentinel(Protocol.SENTINEL_MONITOR, masterName, ip,
String.valueOf(port), String.valueOf(quorum));
return client.getStatusCodeReply();
}
public String sentinelRemove(String masterName) {
client.sentinel(Protocol.SENTINEL_REMOVE, masterName);
return client.getStatusCodeReply();
}
public String sentinelSet(String masterName,
Map<String, String> parameterMap) {
int index = 0;
int paramsLength = parameterMap.size() * 2 + 2;
String[] params = new String[paramsLength];
params[index++] = Protocol.SENTINEL_SET;
params[index++] = masterName;
for (Entry<String, String> entry : parameterMap.entrySet()) {
params[index++] = entry.getKey();
params[index++] = entry.getValue();
}
client.sentinel(params);
return client.getStatusCodeReply();
}
public byte[] dump(final String key) { public byte[] dump(final String key) {
checkIsInMulti(); checkIsInMulti();
client.dump(key); client.dump(key);
return client.getBinaryBulkReply(); return client.getBinaryBulkReply();
} }
public String restore(final String key, final int ttl, final byte[] serializedValue) { public String restore(final String key, final int ttl,
checkIsInMulti(); final byte[] serializedValue) {
client.restore(key, ttl, serializedValue); checkIsInMulti();
return client.getStatusCodeReply(); client.restore(key, ttl, serializedValue);
return client.getStatusCodeReply();
} }
@Deprecated
public Long pexpire(final String key, final int milliseconds) { public Long pexpire(final String key, final int milliseconds) {
checkIsInMulti(); return pexpire(key, (long) milliseconds);
client.pexpire(key, milliseconds); }
return client.getIntegerReply();
public Long pexpire(final String key, final long milliseconds) {
checkIsInMulti();
client.pexpire(key, milliseconds);
return client.getIntegerReply();
} }
public Long pexpireAt(final String key, final long millisecondsTimestamp) { public Long pexpireAt(final String key, final long millisecondsTimestamp) {
checkIsInMulti(); checkIsInMulti();
client.pexpireAt(key, millisecondsTimestamp); client.pexpireAt(key, millisecondsTimestamp);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Long pttl(final String key) { public Long pttl(final String key) {
checkIsInMulti(); checkIsInMulti();
client.pttl(key); client.pttl(key);
return client.getIntegerReply(); return client.getIntegerReply();
} }
public Double incrByFloat(final String key, final double increment) {
checkIsInMulti();
client.incrByFloat(key, increment);
String relpy = client.getBulkReply();
return (relpy != null ? new Double(relpy) : null);
}
public String psetex(final String key, final int milliseconds, final String value) { public String psetex(final String key, final int milliseconds,
checkIsInMulti(); final String value) {
client.psetex(key, milliseconds, value); checkIsInMulti();
return client.getStatusCodeReply(); client.psetex(key, milliseconds, value);
return client.getStatusCodeReply();
} }
public String set(final String key, final String value, final String nxxx) { public String set(final String key, final String value, final String nxxx) {
checkIsInMulti(); checkIsInMulti();
client.set(key, value, nxxx); client.set(key, value, nxxx);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String set(final String key, final String value, final String nxxx, final String expx, final int time) { public String set(final String key, final String value, final String nxxx,
checkIsInMulti(); final String expx, final int time) {
client.set(key, value, nxxx, expx, time); checkIsInMulti();
return client.getStatusCodeReply(); client.set(key, value, nxxx, expx, time);
return client.getStatusCodeReply();
} }
public String clientKill(final String client) { public String clientKill(final String client) {
checkIsInMulti(); checkIsInMulti();
this.client.clientKill(client); this.client.clientKill(client);
return this.client.getStatusCodeReply(); return this.client.getStatusCodeReply();
} }
public String clientSetname(final String name) { public String clientSetname(final String name) {
checkIsInMulti(); checkIsInMulti();
client.clientSetname(name); client.clientSetname(name);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String migrate(final String host, final int port, final String key, final int destinationDb, final int timeout) { public String migrate(final String host, final int port, final String key,
checkIsInMulti(); final int destinationDb, final int timeout) {
client.migrate(host, port, key, destinationDb, timeout); checkIsInMulti();
return client.getStatusCodeReply(); client.migrate(host, port, key, destinationDb, timeout);
} return client.getStatusCodeReply();
public Double hincrByFloat(final String key, final String field, double increment) {
checkIsInMulti();
client.hincrByFloat(key, field, increment);
String relpy = client.getBulkReply();
return (relpy != null ? new Double(relpy) : 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
*/
public ScanResult<String> scan(int cursor) { public ScanResult<String> scan(int cursor) {
return scan(cursor, new ScanParams()); 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) { public ScanResult<String> scan(int cursor, final ScanParams params) {
checkIsInMulti(); checkIsInMulti();
client.scan(cursor, params); client.scan(cursor, params);
List<Object> result = client.getObjectMultiBulkReply(); List<Object> result = client.getObjectMultiBulkReply();
int newcursor = Integer.parseInt(new String((byte[])result.get(0))); int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
List<String> results = new ArrayList<String>(); List<String> results = new ArrayList<String>();
List<byte[]> rawResults = (List<byte[]>)result.get(1); List<byte[]> rawResults = (List<byte[]>) result.get(1);
for (byte[] bs : rawResults) { for (byte[] bs : rawResults) {
results.add(SafeEncoder.encode(bs)); results.add(SafeEncoder.encode(bs));
} }
return new ScanResult<String>(newcursor, results); return new ScanResult<String>(newcursor, results);
} }
public 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
*/
public ScanResult<Map.Entry<String, String>> hscan(final String key,
int cursor) {
return hscan(key, cursor, new ScanParams()); return hscan(key, cursor, new ScanParams());
} }
public ScanResult<Map.Entry<String, String>> 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 ScanResult<Map.Entry<String, String>> hscan(final String key,
int cursor, final ScanParams params) {
checkIsInMulti(); checkIsInMulti();
client.hscan(key, cursor, params); client.hscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply(); List<Object> result = client.getObjectMultiBulkReply();
int newcursor = Integer.parseInt(new String((byte[])result.get(0))); int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
List<Map.Entry<String, String>> results = new ArrayList<Map.Entry<String, String>>(); List<Map.Entry<String, String>> results = new ArrayList<Map.Entry<String, String>>();
List<byte[]> rawResults = (List<byte[]>)result.get(1); List<byte[]> rawResults = (List<byte[]>) result.get(1);
Iterator<byte[]> iterator = rawResults.iterator(); Iterator<byte[]> iterator = rawResults.iterator();
while(iterator.hasNext()) { while (iterator.hasNext()) {
results.add(new AbstractMap.SimpleEntry<String, String>(SafeEncoder.encode(iterator.next()), SafeEncoder.encode(iterator.next()))); results.add(new AbstractMap.SimpleEntry<String, String>(SafeEncoder
.encode(iterator.next()), SafeEncoder.encode(iterator
.next())));
} }
return new ScanResult<Map.Entry<String, String>>(newcursor, results); 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) { public ScanResult<String> sscan(final String key, int cursor) {
return sscan(key, cursor, new ScanParams()); return sscan(key, cursor, new ScanParams());
} }
public ScanResult<String> 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 ScanResult<String> sscan(final String key, int cursor,
final ScanParams params) {
checkIsInMulti(); checkIsInMulti();
client.sscan(key, cursor, params); client.sscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply(); List<Object> result = client.getObjectMultiBulkReply();
int newcursor = Integer.parseInt(new String((byte[])result.get(0))); int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
List<String> results = new ArrayList<String>(); List<String> results = new ArrayList<String>();
List<byte[]> rawResults = (List<byte[]>)result.get(1); List<byte[]> rawResults = (List<byte[]>) result.get(1);
for (byte[] bs : rawResults) { for (byte[] bs : rawResults) {
results.add(SafeEncoder.encode(bs)); results.add(SafeEncoder.encode(bs));
} }
return new ScanResult<String>(newcursor, results); 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) { public ScanResult<Tuple> zscan(final String key, int cursor) {
return zscan(key, cursor, new ScanParams()); return zscan(key, cursor, new ScanParams());
} }
public ScanResult<Tuple> zscan(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 ScanResult<Tuple> zscan(final String key, int cursor,
final ScanParams params) {
checkIsInMulti(); checkIsInMulti();
client.zscan(key, cursor, params); client.zscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply(); List<Object> result = client.getObjectMultiBulkReply();
int newcursor = Integer.parseInt(new String((byte[])result.get(0))); int newcursor = Integer.parseInt(new String((byte[]) result.get(0)));
List<Tuple> results = new ArrayList<Tuple>(); List<Tuple> results = new ArrayList<Tuple>();
List<byte[]> rawResults = (List<byte[]>)result.get(1); List<byte[]> rawResults = (List<byte[]>) result.get(1);
Iterator<byte[]> iterator = rawResults.iterator(); Iterator<byte[]> iterator = rawResults.iterator();
while(iterator.hasNext()) { while (iterator.hasNext()) {
results.add(new Tuple(SafeEncoder.encode(iterator.next()), Double.valueOf(SafeEncoder.encode(iterator.next())))); results.add(new Tuple(SafeEncoder.encode(iterator.next()), Double
.valueOf(SafeEncoder.encode(iterator.next()))));
} }
return new ScanResult<Tuple>(newcursor, results); return new ScanResult<Tuple>(newcursor, results);
} }
public ScanResult<String> scan(final String cursor) {
return scan(cursor, new ScanParams());
}
public ScanResult<String> scan(final String cursor, final ScanParams params) {
checkIsInMulti();
client.scan(cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
String newcursor = 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);
}
public ScanResult<Map.Entry<String, String>> hscan(final String key,
final String cursor) {
return hscan(key, cursor, new ScanParams());
}
public ScanResult<Map.Entry<String, String>> hscan(final String key,
final String cursor, final ScanParams params) {
checkIsInMulti();
client.hscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
String newcursor = 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);
}
public ScanResult<String> sscan(final String key, final String cursor) {
return sscan(key, cursor, new ScanParams());
}
public ScanResult<String> sscan(final String key, final String cursor,
final ScanParams params) {
checkIsInMulti();
client.sscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
String newcursor = 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);
}
public ScanResult<Tuple> zscan(final String key, final String cursor) {
return zscan(key, cursor, new ScanParams());
}
public ScanResult<Tuple> zscan(final String key, final String cursor,
final ScanParams params) {
checkIsInMulti();
client.zscan(key, cursor, params);
List<Object> result = client.getObjectMultiBulkReply();
String newcursor = 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 String clusterNodes() { public String clusterNodes() {
checkIsInMulti(); checkIsInMulti();
client.clusterNodes(); client.clusterNodes();
return client.getBulkReply(); return client.getBulkReply();
} }
public String clusterMeet(final String ip, final int port) { public String clusterMeet(final String ip, final int port) {
checkIsInMulti(); checkIsInMulti();
client.clusterMeet(ip, port); client.clusterMeet(ip, port);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String clusterAddSlots(final int ...slots) { public String clusterAddSlots(final int... slots) {
checkIsInMulti(); checkIsInMulti();
client.clusterAddSlots(slots); client.clusterAddSlots(slots);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String clusterDelSlots(final int ...slots) { public String clusterDelSlots(final int... slots) {
checkIsInMulti(); checkIsInMulti();
client.clusterDelSlots(slots); client.clusterDelSlots(slots);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String clusterInfo() { public String clusterInfo() {
checkIsInMulti(); checkIsInMulti();
client.clusterInfo(); client.clusterInfo();
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public List<String> clusterGetKeysInSlot(final int slot, final int count) { public List<String> clusterGetKeysInSlot(final int slot, final int count) {
checkIsInMulti(); checkIsInMulti();
client.clusterGetKeysInSlot(slot, count); client.clusterGetKeysInSlot(slot, count);
return client.getMultiBulkReply(); return client.getMultiBulkReply();
} }
public String clusterSetSlotNode(final int slot, final String nodeId) { public String clusterSetSlotNode(final int slot, final String nodeId) {
checkIsInMulti(); checkIsInMulti();
client.clusterSetSlotNode(slot, nodeId); client.clusterSetSlotNode(slot, nodeId);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String clusterSetSlotMigrating(final int slot, final String nodeId) { public String clusterSetSlotMigrating(final int slot, final String nodeId) {
checkIsInMulti(); checkIsInMulti();
client.clusterSetSlotMigrating(slot, nodeId); client.clusterSetSlotMigrating(slot, nodeId);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String clusterSetSlotImporting(final int slot, final String nodeId) { public String clusterSetSlotImporting(final int slot, final String nodeId) {
checkIsInMulti(); checkIsInMulti();
client.clusterSetSlotImporting(slot, nodeId); client.clusterSetSlotImporting(slot, nodeId);
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public String asking() { public String clusterSetSlotStable(final int slot) {
checkIsInMulti(); checkIsInMulti();
client.asking(); client.clusterSetSlotStable(slot);
return client.getStatusCodeReply(); 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();
}
public String asking() {
checkIsInMulti();
client.asking();
return client.getStatusCodeReply();
}
public List<String> pubsubChannels(String pattern) {
checkIsInMulti();
client.pubsubChannels(pattern);
return client.getMultiBulkReply();
}
public Long pubsubNumPat() {
checkIsInMulti();
client.pubsubNumPat();
return client.getIntegerReply();
}
public Map<String, String> pubsubNumSub(String... channels) {
checkIsInMulti();
client.pubsubNumSub(channels);
return BuilderFactory.STRING_MAP
.build(client.getBinaryMultiBulkReply());
}
@Override
public void close() {
if (dataSource != null) {
if (client.isBroken()) {
this.dataSource.returnBrokenResource(this);
} else {
this.dataSource.returnResource(this);
}
} else {
client.close();
} }
}
public void setDataSource(Pool<Jedis> jedisPool) {
this.dataSource = jedisPool;
}
public Long pfadd(final String key, final String... elements) {
checkIsInMulti();
client.pfadd(key, elements);
return client.getIntegerReply();
}
public long pfcount(final String key) {
checkIsInMulti();
client.pfcount(key);
return client.getIntegerReply();
}
@Override
public long pfcount(String... keys) {
checkIsInMulti();
client.pfcount(keys);
return client.getIntegerReply();
}
public String pfmerge(final String destkey, final String... sourcekeys) {
checkIsInMulti();
client.pfmerge(destkey, sourcekeys);
return client.getStatusCodeReply();
}
} }

File diff suppressed because it is too large Load Diff

View File

@@ -3,51 +3,101 @@ package redis.clients.jedis;
import redis.clients.jedis.exceptions.JedisAskDataException; import redis.clients.jedis.exceptions.JedisAskDataException;
import redis.clients.jedis.exceptions.JedisClusterException; import redis.clients.jedis.exceptions.JedisClusterException;
import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException; import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisMovedDataException;
import redis.clients.jedis.exceptions.JedisRedirectionException; import redis.clients.jedis.exceptions.JedisRedirectionException;
import redis.clients.util.JedisClusterCRC16; import redis.clients.util.JedisClusterCRC16;
public abstract class JedisClusterCommand<T> { public abstract class JedisClusterCommand<T> {
private boolean asking = false; private JedisClusterConnectionHandler connectionHandler;
private int commandTimeout;
private int redirections;
private JedisClusterConnectionHandler connectionHandler; public JedisClusterCommand(JedisClusterConnectionHandler connectionHandler,
private int commandTimeout; int timeout, int maxRedirections) {
private int redirections; this.connectionHandler = connectionHandler;
// private boolean asking = false; this.commandTimeout = timeout;
this.redirections = maxRedirections;
}
public JedisClusterCommand(JedisClusterConnectionHandler connectionHandler, int timeout, int maxRedirections) { public abstract T execute(Jedis connection);
this.connectionHandler = connectionHandler;
this.commandTimeout = timeout; public T run(String key) {
this.redirections = maxRedirections; if (key == null) {
throw new JedisClusterException(
"No way to dispatch this command to Redis Cluster.");
} }
public abstract T execute(); return runWithRetries(key, this.redirections, false, false);
}
public T run(String key) { private T runWithRetries(String key, int redirections,
try { boolean tryRandomNode, boolean asking) {
if (redirections <= 0) {
if (key == null) { throw new JedisClusterMaxRedirectionsException(
throw new JedisClusterException("No way to dispatch this command to Redis Cluster."); "Too many Cluster redirections?");
} else if (redirections == 0) {
throw new JedisClusterMaxRedirectionsException("Too many Cluster redirections?");
}
connectionHandler.getConnectionFromSlot(JedisClusterCRC16.getSlot(key));
if (asking) {
//TODO: Pipeline asking with the original command to make it faster....
connectionHandler.getConnection().asking();
}
return execute();
} catch (JedisRedirectionException jre) {
return handleRedirection(jre, key);
}
} }
private T handleRedirection(JedisRedirectionException jre, String key) { Jedis connection = null;
if (jre instanceof JedisAskDataException) { try {
asking = true; if (tryRandomNode) {
} connection = connectionHandler.getConnection();
redirections--; } else {
this.connectionHandler.assignSlotToNode(jre.getSlot(), jre.getTargetNode()); connection = connectionHandler
return run(key); .getConnectionFromSlot(JedisClusterCRC16.getSlot(key));
}
if (asking) {
// TODO: Pipeline asking with the original command to make it
// faster....
connection.asking();
// if asking success, reset asking flag
asking = false;
}
return execute(connection);
} catch (JedisConnectionException jce) {
if (tryRandomNode) {
// 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;
} else if (jre instanceof JedisMovedDataException) {
// TODO : In antirez's redis-rb-cluster implementation,
// it rebuilds cluster's slot and node cache
}
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) {
connectionHandler.returnBrokenConnection(connection);
} else {
connectionHandler.returnConnection(connection);
}
}
}
} }

View File

@@ -1,82 +1,127 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.HashMap; import java.util.*;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.util.ClusterNodeInformation;
import redis.clients.util.ClusterNodeInformationParser;
public abstract class JedisClusterConnectionHandler { public abstract class JedisClusterConnectionHandler {
public static ClusterNodeInformationParser nodeInfoParser = new ClusterNodeInformationParser();
protected Map<String, JedisPool> nodes = new HashMap<String, JedisPool>(); protected Map<String, JedisPool> nodes = new HashMap<String, JedisPool>();
protected Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>(); protected Map<Integer, JedisPool> slots = new HashMap<Integer, JedisPool>();
abstract Jedis getConnection(); abstract Jedis getConnection();
abstract Jedis getConnectionFromSlot(int slot);
public JedisClusterConnectionHandler(Set<HostAndPort> nodes) { protected void returnConnection(Jedis connection) {
initializeSlotsCache(nodes); nodes.get(getNodeKey(connection.getClient()))
} .returnResource(connection);
}
public Map<String, JedisPool> getNodes() { public void returnBrokenConnection(Jedis connection) {
return nodes; nodes.get(getNodeKey(connection.getClient())).returnBrokenResource(
} connection);
}
private void initializeSlotsCache(Set<HostAndPort> nodes) { abstract Jedis getConnectionFromSlot(int slot);
for (HostAndPort hostAndPort : nodes) {
JedisPool jp = new JedisPool(hostAndPort.getHost(), hostAndPort.getPort()); public JedisClusterConnectionHandler(Set<HostAndPort> nodes) {
this.nodes.put(hostAndPort.getHost() + hostAndPort.getPort(), jp); initializeSlotsCache(nodes);
discoverClusterNodesAndSlots(jp); }
public Map<String, JedisPool> getNodes() {
return nodes;
}
private void initializeSlotsCache(Set<HostAndPort> startNodes) {
for (HostAndPort hostAndPort : startNodes) {
JedisPool jp = new JedisPool(hostAndPort.getHost(),
hostAndPort.getPort());
this.nodes.clear();
this.slots.clear();
Jedis jedis = null;
try {
jedis = jp.getResource();
discoverClusterNodesAndSlots(jedis);
break;
} catch (JedisConnectionException e) {
if (jedis != null) {
jp.returnBrokenResource(jedis);
jedis = null;
} }
} // try next nodes
} finally {
private void discoverClusterNodesAndSlots(JedisPool jp) { if (jedis != null) {
String localNodes = jp.getResource().clusterNodes(); jp.returnResource(jedis);
for (String nodeInfo : localNodes.split("\n")) {
HostAndPort node = getHostAndPortFromNodeLine(nodeInfo);
JedisPool nodePool = new JedisPool(node.getHost(), node.getPort());
this.nodes.put(node.getHost() + node.getPort(), nodePool);
populateNodeSlots(nodeInfo, nodePool);
} }
}
} }
private void populateNodeSlots(String nodeInfo, JedisPool nodePool) { for (HostAndPort node : startNodes) {
String[] nodeInfoArray = nodeInfo.split(" "); setNodeIfNotExist(node);
if (nodeInfoArray.length > 7) { }
for (int i = 8; i < nodeInfoArray.length; i++) { }
processSlot(nodeInfoArray[i], nodePool);
} 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));
} }
private void processSlot(String slot, JedisPool nodePool) { for (Integer slot : targetSlots) {
if (slot.contains("-")) { slots.put(slot, targetPool);
String[] slotRange = slot.split("-");
for (int i = Integer.valueOf(slotRange[0]); i <= Integer.valueOf(slotRange[1]); i++) {
slots.put(i, nodePool);
}
} else {
slots.put(Integer.valueOf(slot), nodePool);
}
} }
}
private HostAndPort getHostAndPortFromNodeLine(String nodeInfo) { protected JedisPool getRandomConnection() {
String stringHostAndPort = nodeInfo.split(" ",3)[1]; Object[] nodeArray = nodes.values().toArray();
String[] arrayHostAndPort = stringHostAndPort.split(":"); return (JedisPool) (nodeArray[new Random().nextInt(nodeArray.length)]);
return new HostAndPort(arrayHostAndPort[0], Integer.valueOf(arrayHostAndPort[1])); }
}
public void assignSlotToNode(int slot, HostAndPort targetNode) { protected String getNodeKey(HostAndPort hnp) {
JedisPool targetPool = nodes.get(targetNode.getHost() + targetNode.getPort()); return hnp.getHost() + ":" + hnp.getPort();
slots.put(slot, targetPool); }
}
protected String getNodeKey(Client client) {
return client.getHost() + ":" + client.getPort();
}
protected JedisPool getRandomConnection() { private void setNodeIfNotExist(HostAndPort node) {
Object[] nodeArray = nodes.values().toArray(); String nodeKey = getNodeKey(node);
return (JedisPool) (nodeArray[new Random().nextInt(nodeArray.length)]); if (nodes.containsKey(nodeKey))
} return;
JedisPool nodePool = new JedisPool(node.getHost(), node.getPort());
nodes.put(nodeKey, nodePool);
}
} }

View File

@@ -7,10 +7,12 @@ import java.util.Set;
/** /**
* Common interface for sharded and non-sharded Jedis * Common interface for sharded and non-sharded Jedis
*/ */
public interface public interface JedisCommands {
JedisCommands {
String set(String key, String value); String set(String key, String value);
String set(String key, String value, String nxxx,
String expx, long time);
String get(String key); String get(String key);
Boolean exists(String key); Boolean exists(String key);
@@ -115,7 +117,7 @@ public interface
Long zadd(String key, double score, String member); Long zadd(String key, double score, String member);
Long zadd(String key, Map<Double, String> scoreMembers); Long zadd(String key, Map<String, Double> scoreMembers);
Set<String> zrange(String key, long start, long end); Set<String> zrange(String key, long start, long end);
@@ -152,38 +154,38 @@ public interface
Set<String> zrevrangeByScore(String key, double max, double min); Set<String> zrevrangeByScore(String key, double max, double min);
Set<String> zrangeByScore(String key, double min, double max, int offset, Set<String> zrangeByScore(String key, double min, double max, int offset,
int count); int count);
Set<String> zrevrangeByScore(String key, String max, String min); Set<String> zrevrangeByScore(String key, String max, String min);
Set<String> zrangeByScore(String key, String min, String max, int offset, Set<String> zrangeByScore(String key, String min, String max, int offset,
int count); int count);
Set<String> zrevrangeByScore(String key, double max, double min, Set<String> zrevrangeByScore(String key, double max, double min,
int offset, int count); int offset, int count);
Set<Tuple> zrangeByScoreWithScores(String key, double min, double max); Set<Tuple> zrangeByScoreWithScores(String key, double min, double max);
Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min); Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min);
Set<Tuple> zrangeByScoreWithScores(String key, double min, double max, Set<Tuple> zrangeByScoreWithScores(String key, double min, double max,
int offset, int count); int offset, int count);
Set<String> zrevrangeByScore(String key, String max, String min, Set<String> zrevrangeByScore(String key, String max, String min,
int offset, int count); int offset, int count);
Set<Tuple> zrangeByScoreWithScores(String key, String min, String max); Set<Tuple> zrangeByScoreWithScores(String key, String min, String max);
Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min); Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min);
Set<Tuple> zrangeByScoreWithScores(String key, String min, String max, Set<Tuple> zrangeByScoreWithScores(String key, String min, String max,
int offset, int count); int offset, int count);
Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min, Set<Tuple> zrevrangeByScoreWithScores(String key, double max, double min,
int offset, int count); int offset, int count);
Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min, Set<Tuple> zrevrangeByScoreWithScores(String key, String max, String min,
int offset, int count); int offset, int count);
Long zremrangeByRank(String key, long start, long end); Long zremrangeByRank(String key, long start, long end);
@@ -192,7 +194,7 @@ public interface
Long zremrangeByScore(String key, String start, String end); Long zremrangeByScore(String key, String start, String end);
Long linsert(String key, Client.LIST_POSITION where, String pivot, Long linsert(String key, Client.LIST_POSITION where, String pivot,
String value); String value);
Long lpushx(String key, String... string); Long lpushx(String key, String... string);
@@ -212,9 +214,38 @@ public interface
Long bitcount(final String key, long start, long end); 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); 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); 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<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);
ScanResult<Tuple> zscan(final String key, final String cursor);
Long pfadd(final String key, final String... elements);
long pfcount(final String key);
} }

View File

@@ -4,12 +4,12 @@ public abstract class JedisMonitor {
protected Client client; protected Client client;
public void proceed(Client client) { public void proceed(Client client) {
this.client = client; this.client = client;
this.client.setTimeoutInfinite(); this.client.setTimeoutInfinite();
do { do {
String command = client.getBulkReply(); String command = client.getBulkReply();
onCommand(command); onCommand(command);
} while (client.isConnected()); } while (client.isConnected());
} }
public abstract void onCommand(String command); public abstract void onCommand(String command);

View File

@@ -79,11 +79,23 @@ public class JedisPool extends Pool<Jedis> {
database, clientName)); database, clientName));
} }
@Override
public Jedis getResource() {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
}
public void returnBrokenResource(final Jedis resource) { public void returnBrokenResource(final Jedis resource) {
returnBrokenResourceObject(resource); if (resource != null) {
returnBrokenResourceObject(resource);
}
} }
public void returnResource(final Jedis resource) { public void returnResource(final Jedis resource) {
returnResourceObject(resource); if (resource != null) {
resource.resetState();
returnResourceObject(resource);
}
} }
} }

View File

@@ -4,10 +4,10 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
public class JedisPoolConfig extends GenericObjectPoolConfig { public class JedisPoolConfig extends GenericObjectPoolConfig {
public JedisPoolConfig() { public JedisPoolConfig() {
// defaults to make your life with connection pool easier :) // defaults to make your life with connection pool easier :)
setTestWhileIdle(true); setTestWhileIdle(true);
setMinEvictableIdleTimeMillis(60000); setMinEvictableIdleTimeMillis(60000);
setTimeBetweenEvictionRunsMillis(30000); setTimeBetweenEvictionRunsMillis(30000);
setNumTestsPerEvictionRun(-1); setNumTestsPerEvictionRun(-1);
} }
} }

View File

@@ -16,12 +16,12 @@ import redis.clients.util.SafeEncoder;
public abstract class JedisPubSub { public abstract class JedisPubSub {
private int subscribedChannels = 0; private int subscribedChannels = 0;
private Client client; private volatile Client client;
public abstract void onMessage(String channel, String message); public abstract void onMessage(String channel, String message);
public abstract void onPMessage(String pattern, String channel, public abstract void onPMessage(String pattern, String channel,
String message); String message);
public abstract void onSubscribe(String channel, int subscribedChannels); public abstract void onSubscribe(String channel, int subscribedChannels);
@@ -32,115 +32,139 @@ public abstract class JedisPubSub {
public abstract void onPSubscribe(String pattern, int subscribedChannels); public abstract void onPSubscribe(String pattern, int subscribedChannels);
public void unsubscribe() { public void unsubscribe() {
if (client == null) { if (client == null) {
throw new JedisConnectionException( throw new JedisConnectionException(
"JedisPubSub was not subscribed to a Jedis instance."); "JedisPubSub was not subscribed to a Jedis instance.");
} }
client.unsubscribe(); client.unsubscribe();
client.flush(); client.flush();
} }
public void unsubscribe(String... channels) { public void unsubscribe(String... channels) {
client.unsubscribe(channels); if (client == null) {
client.flush(); throw new JedisConnectionException(
"JedisPubSub is not subscribed to a Jedis instance.");
}
client.unsubscribe(channels);
client.flush();
} }
public void subscribe(String... channels) { public void subscribe(String... channels) {
client.subscribe(channels); if (client == null) {
client.flush(); throw new JedisConnectionException(
"JedisPubSub is not subscribed to a Jedis instance.");
}
client.subscribe(channels);
client.flush();
} }
public void psubscribe(String... patterns) { public void psubscribe(String... patterns) {
client.psubscribe(patterns); if (client == null) {
client.flush(); throw new JedisConnectionException(
"JedisPubSub is not subscribed to a Jedis instance.");
}
client.psubscribe(patterns);
client.flush();
} }
public void punsubscribe() { public void punsubscribe() {
client.punsubscribe(); if (client == null) {
client.flush(); throw new JedisConnectionException(
"JedisPubSub is not subscribed to a Jedis instance.");
}
client.punsubscribe();
client.flush();
} }
public void punsubscribe(String... patterns) { public void punsubscribe(String... patterns) {
client.punsubscribe(patterns); if (client == null) {
client.flush(); throw new JedisConnectionException(
"JedisPubSub is not subscribed to a Jedis instance.");
}
client.punsubscribe(patterns);
client.flush();
} }
public boolean isSubscribed() { public boolean isSubscribed() {
return subscribedChannels > 0; return subscribedChannels > 0;
} }
public void proceedWithPatterns(Client client, String... patterns) { public void proceedWithPatterns(Client client, String... patterns) {
this.client = client; this.client = client;
client.psubscribe(patterns); client.psubscribe(patterns);
client.flush(); client.flush();
process(client); process(client);
} }
public void proceed(Client client, String... channels) { public void proceed(Client client, String... channels) {
this.client = client; this.client = client;
client.subscribe(channels); client.subscribe(channels);
client.flush(); client.flush();
process(client); process(client);
} }
private void process(Client client) { private void process(Client client) {
do {
List<Object> reply = client.getObjectMultiBulkReply(); do {
final Object firstObj = reply.get(0); List<Object> reply = client.getRawObjectMultiBulkReply();
if (!(firstObj instanceof byte[])) { final Object firstObj = reply.get(0);
throw new JedisException("Unknown message type: " + firstObj); if (!(firstObj instanceof byte[])) {
} throw new JedisException("Unknown message type: " + firstObj);
final byte[] resp = (byte[]) firstObj; }
if (Arrays.equals(SUBSCRIBE.raw, resp)) { final byte[] resp = (byte[]) firstObj;
subscribedChannels = ((Long) reply.get(2)).intValue(); if (Arrays.equals(SUBSCRIBE.raw, resp)) {
final byte[] bchannel = (byte[]) reply.get(1); subscribedChannels = ((Long) reply.get(2)).intValue();
final String strchannel = (bchannel == null) ? null final byte[] bchannel = (byte[]) reply.get(1);
: SafeEncoder.encode(bchannel); final String strchannel = (bchannel == null) ? null
onSubscribe(strchannel, subscribedChannels); : SafeEncoder.encode(bchannel);
} else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { onSubscribe(strchannel, subscribedChannels);
subscribedChannels = ((Long) reply.get(2)).intValue(); } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) {
final byte[] bchannel = (byte[]) reply.get(1); subscribedChannels = ((Long) reply.get(2)).intValue();
final String strchannel = (bchannel == null) ? null final byte[] bchannel = (byte[]) reply.get(1);
: SafeEncoder.encode(bchannel); final String strchannel = (bchannel == null) ? null
onUnsubscribe(strchannel, subscribedChannels); : SafeEncoder.encode(bchannel);
} else if (Arrays.equals(MESSAGE.raw, resp)) { onUnsubscribe(strchannel, subscribedChannels);
final byte[] bchannel = (byte[]) reply.get(1); } else if (Arrays.equals(MESSAGE.raw, resp)) {
final byte[] bmesg = (byte[]) reply.get(2); final byte[] bchannel = (byte[]) reply.get(1);
final String strchannel = (bchannel == null) ? null final byte[] bmesg = (byte[]) reply.get(2);
: SafeEncoder.encode(bchannel); final String strchannel = (bchannel == null) ? null
final String strmesg = (bmesg == null) ? null : SafeEncoder : SafeEncoder.encode(bchannel);
.encode(bmesg); final String strmesg = (bmesg == null) ? null : SafeEncoder
onMessage(strchannel, strmesg); .encode(bmesg);
} else if (Arrays.equals(PMESSAGE.raw, resp)) { onMessage(strchannel, strmesg);
final byte[] bpattern = (byte[]) reply.get(1); } else if (Arrays.equals(PMESSAGE.raw, resp)) {
final byte[] bchannel = (byte[]) reply.get(2); final byte[] bpattern = (byte[]) reply.get(1);
final byte[] bmesg = (byte[]) reply.get(3); final byte[] bchannel = (byte[]) reply.get(2);
final String strpattern = (bpattern == null) ? null final byte[] bmesg = (byte[]) reply.get(3);
: SafeEncoder.encode(bpattern); final String strpattern = (bpattern == null) ? null
final String strchannel = (bchannel == null) ? null : SafeEncoder.encode(bpattern);
: SafeEncoder.encode(bchannel); final String strchannel = (bchannel == null) ? null
final String strmesg = (bmesg == null) ? null : SafeEncoder : SafeEncoder.encode(bchannel);
.encode(bmesg); final String strmesg = (bmesg == null) ? null : SafeEncoder
onPMessage(strpattern, strchannel, strmesg); .encode(bmesg);
} else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { onPMessage(strpattern, strchannel, strmesg);
subscribedChannels = ((Long) reply.get(2)).intValue(); } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) {
final byte[] bpattern = (byte[]) reply.get(1); subscribedChannels = ((Long) reply.get(2)).intValue();
final String strpattern = (bpattern == null) ? null final byte[] bpattern = (byte[]) reply.get(1);
: SafeEncoder.encode(bpattern); final String strpattern = (bpattern == null) ? null
onPSubscribe(strpattern, subscribedChannels); : SafeEncoder.encode(bpattern);
} else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { onPSubscribe(strpattern, subscribedChannels);
subscribedChannels = ((Long) reply.get(2)).intValue(); } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) {
final byte[] bpattern = (byte[]) reply.get(1); subscribedChannels = ((Long) reply.get(2)).intValue();
final String strpattern = (bpattern == null) ? null final byte[] bpattern = (byte[]) reply.get(1);
: SafeEncoder.encode(bpattern); final String strpattern = (bpattern == null) ? null
onPUnsubscribe(strpattern, subscribedChannels); : SafeEncoder.encode(bpattern);
} else { onPUnsubscribe(strpattern, subscribedChannels);
throw new JedisException("Unknown message type: " + firstObj); } else {
} throw new JedisException("Unknown message type: " + firstObj);
} while (isSubscribed()); }
} while (isSubscribed());
/* Invalidate instance since this thread is no longer listening */
this.client = null;
} }
public int getSubscribedChannels() { public int getSubscribedChannels() {
return subscribedChannels; return subscribedChannels;
} }
} }

View File

@@ -4,17 +4,16 @@ import java.util.Set;
public class JedisRandomConnectionHandler extends JedisClusterConnectionHandler { public class JedisRandomConnectionHandler extends JedisClusterConnectionHandler {
public JedisRandomConnectionHandler(Set<HostAndPort> nodes) {
super(nodes);
}
public JedisRandomConnectionHandler(Set<HostAndPort> nodes) { public Jedis getConnection() {
super(nodes); return getRandomConnection().getResource();
} }
public Jedis getConnection() { @Override
return getRandomConnection().getResource(); Jedis getConnectionFromSlot(int slot) {
} return getRandomConnection().getResource();
}
@Override
Jedis getConnectionFromSlot(int slot) {
return getRandomConnection().getResource();
}
} }

View File

@@ -74,14 +74,6 @@ public class JedisSentinelPool extends Pool<Jedis> {
initPool(master); initPool(master);
} }
public void returnBrokenResource(final Jedis resource) {
returnBrokenResourceObject(resource);
}
public void returnResource(final Jedis resource) {
returnResourceObject(resource);
}
private volatile HostAndPort currentHostMaster; private volatile HostAndPort currentHostMaster;
public void destroy() { public void destroy() {
@@ -100,8 +92,9 @@ public class JedisSentinelPool extends Pool<Jedis> {
if (!master.equals(currentHostMaster)) { if (!master.equals(currentHostMaster)) {
currentHostMaster = master; currentHostMaster = master;
log.info("Created JedisPool to master at " + master); log.info("Created JedisPool to master at " + master);
initPool(poolConfig, new JedisFactory(master.getHost(), master.getPort(), initPool(poolConfig,
timeout, password, database)); new JedisFactory(master.getHost(), master.getPort(),
timeout, password, database));
} }
} }
@@ -163,10 +156,30 @@ public class JedisSentinelPool extends Pool<Jedis> {
} }
private HostAndPort toHostAndPort(List<String> getMasterAddrByNameResult) { private HostAndPort toHostAndPort(List<String> getMasterAddrByNameResult) {
String host = getMasterAddrByNameResult.get(0); String host = getMasterAddrByNameResult.get(0);
int port = Integer.parseInt(getMasterAddrByNameResult.get(1)); int port = Integer.parseInt(getMasterAddrByNameResult.get(1));
return new HostAndPort(host, port); return new HostAndPort(host, port);
}
@Override
public Jedis getResource() {
Jedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
}
public void returnBrokenResource(final Jedis resource) {
if (resource != null) {
returnBrokenResourceObject(resource);
}
}
public void returnResource(final Jedis resource) {
if (resource != null) {
resource.resetState();
returnResourceObject(resource);
}
} }
protected class JedisPubSubAdapter extends JedisPubSub { protected class JedisPubSubAdapter extends JedisPubSub {

View File

@@ -1,48 +1,72 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set; import java.util.Set;
public class JedisSlotBasedConnectionHandler extends JedisClusterConnectionHandler { import redis.clients.jedis.exceptions.JedisConnectionException;
private Jedis currentConnection; public class JedisSlotBasedConnectionHandler extends
JedisClusterConnectionHandler {
public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes) { public JedisSlotBasedConnectionHandler(Set<HostAndPort> nodes) {
super(nodes); super(nodes);
} }
public Jedis getConnection() {
// In antirez's redis-rb-cluster implementation,
// getRandomConnection always return valid connection (able to ping-pong)
// or exception if all connections are invalid
public Jedis getConnection() { List<JedisPool> pools = getShuffledNodesPool();
return currentConnection != null ? currentConnection : getRandomConnection().getResource();
}
for (JedisPool pool : pools) {
Jedis jedis = null;
try {
jedis = pool.getResource();
if (jedis == null) {
continue;
private void returnCurrentConnection() {
if (currentConnection != null) {
nodes.get(currentConnection.getClient().getHost()+currentConnection.getClient().getPort()).returnResource(currentConnection);
} }
} String result = jedis.ping();
if (result.equalsIgnoreCase("pong"))
return jedis;
@Override pool.returnBrokenResource(jedis);
public void assignSlotToNode(int slot, HostAndPort targetNode) { } catch (JedisConnectionException ex) {
super.assignSlotToNode(slot, targetNode); if (jedis != null) {
getConnectionFromSlot(slot); pool.returnBrokenResource(jedis);
}
@Override
public Jedis getConnectionFromSlot(int slot) {
returnCurrentConnection();
JedisPool connectionPool = slots.get(slot);
if (connectionPool == null) {
connectionPool = getRandomConnection();
} }
currentConnection = connectionPool.getResource(); }
return connectionPool.getResource();
} }
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);
if (connectionPool != null) {
// It can't guaranteed to get valid connection because of node assignment
return connectionPool.getResource();
} else {
return getConnection();
}
}
private List<JedisPool> getShuffledNodesPool() {
List<JedisPool> pools = new ArrayList<JedisPool>();
pools.addAll(nodes.values());
Collections.shuffle(pools);
return pools;
}
} }

View File

@@ -1,6 +1,5 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
@@ -70,4 +69,8 @@ public interface MultiKeyBinaryCommands {
byte[] randomBinaryKey(); byte[] randomBinaryKey();
Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys); Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys);
String pfmerge(final byte[] destkey, final byte[]... sourcekeys);
Long pfcount(byte[]... keys);
} }

View File

@@ -1,11 +1,11 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* Multikey related commands (these are split out because they are non-shardable) * Multikey related commands (these are split out because they are
* non-shardable)
*/ */
public interface MultiKeyBinaryRedisPipeline { public interface MultiKeyBinaryRedisPipeline {
@@ -39,7 +39,8 @@ public interface MultiKeyBinaryRedisPipeline {
Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member); Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member);
Response<Long> sort(byte[] key, SortingParams sortingParameters, byte[] dstkey); Response<Long> sort(byte[] key, SortingParams sortingParameters,
byte[] dstkey);
Response<Long> sort(byte[] key, byte[] dstkey); Response<Long> sort(byte[] key, byte[] dstkey);
@@ -64,4 +65,8 @@ public interface MultiKeyBinaryRedisPipeline {
Response<byte[]> randomKeyBinary(); Response<byte[]> randomKeyBinary();
Response<Long> bitop(BitOP op, final byte[] destKey, byte[]... srcKeys); Response<Long> bitop(BitOP op, final byte[] destKey, byte[]... srcKeys);
Response<String> pfmerge(final byte[] destkey, final byte[]... sourcekeys);
Response<Long> pfcount(final byte[] ... keys);
} }

View File

@@ -1,8 +1,6 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
import java.util.Map;
import java.util.Set; import java.util.Set;
public interface MultiKeyCommands { public interface MultiKeyCommands {
@@ -72,5 +70,17 @@ public interface MultiKeyCommands {
Long bitop(BitOP op, final String destKey, String... srcKeys); 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(int cursor);
ScanResult<String> scan(final String cursor);
String pfmerge(final String destkey, final String... sourcekeys);
long pfcount(final String...keys);
} }

View File

@@ -1,12 +1,11 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.util.List; import java.util.List;
import java.util.Set; import java.util.Set;
/** /**
* Multikey related commands (these are split out because they are non-shardable) * Multikey related commands (these are split out because they are
* non-shardable)
*/ */
public interface MultiKeyCommandsPipeline { public interface MultiKeyCommandsPipeline {
Response<Long> del(String... keys); Response<Long> del(String... keys);
@@ -39,7 +38,8 @@ public interface MultiKeyCommandsPipeline {
Response<Long> smove(String srckey, String dstkey, String member); Response<Long> smove(String srckey, String dstkey, String member);
Response<Long> sort(String key, SortingParams sortingParameters, String dstkey); Response<Long> sort(String key, SortingParams sortingParameters,
String dstkey);
Response<Long> sort(String key, String dstkey); Response<Long> sort(String key, String dstkey);
@@ -64,4 +64,8 @@ public interface MultiKeyCommandsPipeline {
Response<String> randomKey(); Response<String> randomKey();
Response<Long> bitop(BitOP op, final String destKey, String... srcKeys); Response<Long> bitop(BitOP op, final String destKey, String... srcKeys);
Response<String> pfmerge(final String destkey, final String... sourcekeys);
Response<Long> pfcount(final String...keys);
} }

View File

@@ -5,399 +5,402 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
abstract class MultiKeyPipelineBase extends PipelineBase implements abstract class MultiKeyPipelineBase extends PipelineBase implements
BasicRedisPipeline, BasicRedisPipeline, MultiKeyBinaryRedisPipeline,
MultiKeyBinaryRedisPipeline, MultiKeyCommandsPipeline, ClusterPipeline {
MultiKeyCommandsPipeline,
ClusterPipeline {
protected Client client = null; protected Client client = null;
public Response<List<String>> brpop(String... args) { public Response<List<String>> brpop(String... args) {
client.brpop(args); client.brpop(args);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<List<String>> brpop(int timeout, String... keys) { public Response<List<String>> brpop(int timeout, String... keys) {
client.brpop(timeout, keys); client.brpop(timeout, keys);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<List<String>> blpop(String... args) { public Response<List<String>> blpop(String... args) {
client.blpop(args); client.blpop(args);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<List<String>> blpop(int timeout, String... keys) { public Response<List<String>> blpop(int timeout, String... keys) {
client.blpop(timeout, keys); client.blpop(timeout, keys);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<Map<String, String>> blpopMap(int timeout, String... keys) { public Response<Map<String, String>> blpopMap(int timeout, String... keys) {
client.blpop(timeout, keys); client.blpop(timeout, keys);
return getResponse(BuilderFactory.STRING_MAP); return getResponse(BuilderFactory.STRING_MAP);
} }
public Response<List<byte[]>> brpop(byte[]... args) { public Response<List<byte[]>> brpop(byte[]... args) {
client.brpop(args); client.brpop(args);
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); return getResponse(BuilderFactory.BYTE_ARRAY_LIST);
} }
public Response<List<String>> brpop(int timeout, byte[]... keys) { public Response<List<String>> brpop(int timeout, byte[]... keys) {
client.brpop(timeout, keys); client.brpop(timeout, keys);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<Map<String, String>> brpopMap(int timeout, String... keys) { public Response<Map<String, String>> brpopMap(int timeout, String... keys) {
client.blpop(timeout, keys); client.blpop(timeout, keys);
return getResponse(BuilderFactory.STRING_MAP); return getResponse(BuilderFactory.STRING_MAP);
} }
public Response<List<byte[]>> blpop(byte[]... args) { public Response<List<byte[]>> blpop(byte[]... args) {
client.blpop(args); client.blpop(args);
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); return getResponse(BuilderFactory.BYTE_ARRAY_LIST);
} }
public Response<List<String>> blpop(int timeout, byte[]... keys) { public Response<List<String>> blpop(int timeout, byte[]... keys) {
client.blpop(timeout, keys); client.blpop(timeout, keys);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<Long> del(String... keys) { public Response<Long> del(String... keys) {
client.del(keys); client.del(keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> del(byte[]... keys) { public Response<Long> del(byte[]... keys) {
client.del(keys); client.del(keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Set<String>> keys(String pattern) { public Response<Set<String>> keys(String pattern) {
getClient(pattern).keys(pattern); getClient(pattern).keys(pattern);
return getResponse(BuilderFactory.STRING_SET); return getResponse(BuilderFactory.STRING_SET);
} }
public Response<Set<byte[]>> keys(byte[] pattern) { public Response<Set<byte[]>> keys(byte[] pattern) {
getClient(pattern).keys(pattern); getClient(pattern).keys(pattern);
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
} }
public Response<List<String>> mget(String... keys) { public Response<List<String>> mget(String... keys) {
client.mget(keys); client.mget(keys);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<List<byte[]>> mget(byte[]... keys) { public Response<List<byte[]>> mget(byte[]... keys) {
client.mget(keys); client.mget(keys);
return getResponse(BuilderFactory.BYTE_ARRAY_LIST); return getResponse(BuilderFactory.BYTE_ARRAY_LIST);
} }
public Response<String> mset(String... keysvalues) { public Response<String> mset(String... keysvalues) {
client.mset(keysvalues); client.mset(keysvalues);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> mset(byte[]... keysvalues) { public Response<String> mset(byte[]... keysvalues) {
client.mset(keysvalues); client.mset(keysvalues);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<Long> msetnx(String... keysvalues) { public Response<Long> msetnx(String... keysvalues) {
client.msetnx(keysvalues); client.msetnx(keysvalues);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> msetnx(byte[]... keysvalues) { public Response<Long> msetnx(byte[]... keysvalues) {
client.msetnx(keysvalues); client.msetnx(keysvalues);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> rename(String oldkey, String newkey) { public Response<String> rename(String oldkey, String newkey) {
client.rename(oldkey, newkey); client.rename(oldkey, newkey);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> rename(byte[] oldkey, byte[] newkey) { public Response<String> rename(byte[] oldkey, byte[] newkey) {
client.rename(oldkey, newkey); client.rename(oldkey, newkey);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<Long> renamenx(String oldkey, String newkey) { public Response<Long> renamenx(String oldkey, String newkey) {
client.renamenx(oldkey, newkey); client.renamenx(oldkey, newkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> renamenx(byte[] oldkey, byte[] newkey) { public Response<Long> renamenx(byte[] oldkey, byte[] newkey) {
client.renamenx(oldkey, newkey); client.renamenx(oldkey, newkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> rpoplpush(String srckey, String dstkey) { public Response<String> rpoplpush(String srckey, String dstkey) {
client.rpoplpush(srckey, dstkey); client.rpoplpush(srckey, dstkey);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<byte[]> rpoplpush(byte[] srckey, byte[] dstkey) { public Response<byte[]> rpoplpush(byte[] srckey, byte[] dstkey) {
client.rpoplpush(srckey, dstkey); client.rpoplpush(srckey, dstkey);
return getResponse(BuilderFactory.BYTE_ARRAY); return getResponse(BuilderFactory.BYTE_ARRAY);
} }
public Response<Set<String>> sdiff(String... keys) { public Response<Set<String>> sdiff(String... keys) {
client.sdiff(keys); client.sdiff(keys);
return getResponse(BuilderFactory.STRING_SET); return getResponse(BuilderFactory.STRING_SET);
} }
public Response<Set<byte[]>> sdiff(byte[]... keys) { public Response<Set<byte[]>> sdiff(byte[]... keys) {
client.sdiff(keys); client.sdiff(keys);
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
} }
public Response<Long> sdiffstore(String dstkey, String... keys) { public Response<Long> sdiffstore(String dstkey, String... keys) {
client.sdiffstore(dstkey, keys); client.sdiffstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sdiffstore(byte[] dstkey, byte[]... keys) { public Response<Long> sdiffstore(byte[] dstkey, byte[]... keys) {
client.sdiffstore(dstkey, keys); client.sdiffstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Set<String>> sinter(String... keys) { public Response<Set<String>> sinter(String... keys) {
client.sinter(keys); client.sinter(keys);
return getResponse(BuilderFactory.STRING_SET); return getResponse(BuilderFactory.STRING_SET);
} }
public Response<Set<byte[]>> sinter(byte[]... keys) { public Response<Set<byte[]>> sinter(byte[]... keys) {
client.sinter(keys); client.sinter(keys);
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
} }
public Response<Long> sinterstore(String dstkey, String... keys) { public Response<Long> sinterstore(String dstkey, String... keys) {
client.sinterstore(dstkey, keys); client.sinterstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sinterstore(byte[] dstkey, byte[]... keys) { public Response<Long> sinterstore(byte[] dstkey, byte[]... keys) {
client.sinterstore(dstkey, keys); client.sinterstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> smove(String srckey, String dstkey, String member) { public Response<Long> smove(String srckey, String dstkey, String member) {
client.smove(srckey, dstkey, member); client.smove(srckey, dstkey, member);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member) { public Response<Long> smove(byte[] srckey, byte[] dstkey, byte[] member) {
client.smove(srckey, dstkey, member); client.smove(srckey, dstkey, member);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sort(String key, public Response<Long> sort(String key, SortingParams sortingParameters,
SortingParams sortingParameters, String dstkey) { String dstkey) {
client.sort(key, sortingParameters, dstkey); client.sort(key, sortingParameters, dstkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sort(byte[] key, public Response<Long> sort(byte[] key, SortingParams sortingParameters,
SortingParams sortingParameters, byte[] dstkey) { byte[] dstkey) {
client.sort(key, sortingParameters, dstkey); client.sort(key, sortingParameters, dstkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sort(String key, String dstkey) { public Response<Long> sort(String key, String dstkey) {
client.sort(key, dstkey); client.sort(key, dstkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sort(byte[] key, byte[] dstkey) { public Response<Long> sort(byte[] key, byte[] dstkey) {
client.sort(key, dstkey); client.sort(key, dstkey);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Set<String>> sunion(String... keys) { public Response<Set<String>> sunion(String... keys) {
client.sunion(keys); client.sunion(keys);
return getResponse(BuilderFactory.STRING_SET); return getResponse(BuilderFactory.STRING_SET);
} }
public Response<Set<byte[]>> sunion(byte[]... keys) { public Response<Set<byte[]>> sunion(byte[]... keys) {
client.sunion(keys); client.sunion(keys);
return getResponse(BuilderFactory.BYTE_ARRAY_ZSET); return getResponse(BuilderFactory.BYTE_ARRAY_ZSET);
} }
public Response<Long> sunionstore(String dstkey, String... keys) { public Response<Long> sunionstore(String dstkey, String... keys) {
client.sunionstore(dstkey, keys); client.sunionstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> sunionstore(byte[] dstkey, byte[]... keys) { public Response<Long> sunionstore(byte[] dstkey, byte[]... keys) {
client.sunionstore(dstkey, keys); client.sunionstore(dstkey, keys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> watch(String... keys) { public Response<String> watch(String... keys) {
client.watch(keys); client.watch(keys);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> watch(byte[]... keys) { public Response<String> watch(byte[]... keys) {
client.watch(keys); client.watch(keys);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<Long> zinterstore(String dstkey, String... sets) { public Response<Long> zinterstore(String dstkey, String... sets) {
client.zinterstore(dstkey, sets); client.zinterstore(dstkey, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zinterstore(byte[] dstkey, byte[]... sets) { public Response<Long> zinterstore(byte[] dstkey, byte[]... sets) {
client.zinterstore(dstkey, sets); client.zinterstore(dstkey, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zinterstore(String dstkey, ZParams params, public Response<Long> zinterstore(String dstkey, ZParams params,
String... sets) { String... sets) {
client.zinterstore(dstkey, params, sets); client.zinterstore(dstkey, params, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zinterstore(byte[] dstkey, ZParams params, public Response<Long> zinterstore(byte[] dstkey, ZParams params,
byte[]... sets) { byte[]... sets) {
client.zinterstore(dstkey, params, sets); client.zinterstore(dstkey, params, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zunionstore(String dstkey, String... sets) { public Response<Long> zunionstore(String dstkey, String... sets) {
client.zunionstore(dstkey, sets); client.zunionstore(dstkey, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zunionstore(byte[] dstkey, byte[]... sets) { public Response<Long> zunionstore(byte[] dstkey, byte[]... sets) {
client.zunionstore(dstkey, sets); client.zunionstore(dstkey, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zunionstore(String dstkey, ZParams params, public Response<Long> zunionstore(String dstkey, ZParams params,
String... sets) { String... sets) {
client.zunionstore(dstkey, params, sets); client.zunionstore(dstkey, params, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> zunionstore(byte[] dstkey, ZParams params, public Response<Long> zunionstore(byte[] dstkey, ZParams params,
byte[]... sets) { byte[]... sets) {
client.zunionstore(dstkey, params, sets); client.zunionstore(dstkey, params, sets);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> bgrewriteaof() { public Response<String> bgrewriteaof() {
client.bgrewriteaof(); client.bgrewriteaof();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> bgsave() { public Response<String> bgsave() {
client.bgsave(); client.bgsave();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> configGet(String pattern) { public Response<String> configGet(String pattern) {
client.configGet(pattern); client.configGet(pattern);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> configSet(String parameter, String value) { public Response<String> configSet(String parameter, String value) {
client.configSet(parameter, value); client.configSet(parameter, value);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> brpoplpush(String source, String destination, public Response<String> brpoplpush(String source, String destination,
int timeout) { int timeout) {
client.brpoplpush(source, destination, timeout); client.brpoplpush(source, destination, timeout);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<byte[]> brpoplpush(byte[] source, byte[] destination, public Response<byte[]> brpoplpush(byte[] source, byte[] destination,
int timeout) { int timeout) {
client.brpoplpush(source, destination, timeout); client.brpoplpush(source, destination, timeout);
return getResponse(BuilderFactory.BYTE_ARRAY); return getResponse(BuilderFactory.BYTE_ARRAY);
} }
public Response<String> configResetStat() { public Response<String> configResetStat() {
client.configResetStat(); client.configResetStat();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> save() { public Response<String> save() {
client.save(); client.save();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<Long> lastsave() { public Response<Long> lastsave() {
client.lastsave(); client.lastsave();
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> publish(String channel, String message) { public Response<Long> publish(String channel, String message) {
client.publish(channel, message); client.publish(channel, message);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> publish(byte[] channel, byte[] message) { public Response<Long> publish(byte[] channel, byte[] message) {
client.publish(channel, message); client.publish(channel, message);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> randomKey() { public Response<String> randomKey() {
client.randomKey(); client.randomKey();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<byte[]> randomKeyBinary() { public Response<byte[]> randomKeyBinary() {
client.randomKey(); client.randomKey();
return getResponse(BuilderFactory.BYTE_ARRAY); return getResponse(BuilderFactory.BYTE_ARRAY);
} }
public Response<String> flushDB() { public Response<String> flushDB() {
client.flushDB(); client.flushDB();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> flushAll() { public Response<String> flushAll() {
client.flushAll(); client.flushAll();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> info() { public Response<String> info() {
client.info(); client.info();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
}
public Response<List<String>> time() {
client.time();
return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<Long> dbSize() { public Response<Long> dbSize() {
client.dbSize(); client.dbSize();
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> shutdown() { public Response<String> shutdown() {
client.shutdown(); client.shutdown();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> ping() { public Response<String> ping() {
client.ping(); client.ping();
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> select(int index) { public Response<String> select(int index) {
client.select(index); client.select(index);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<Long> bitop(BitOP op, byte[] destKey, byte[]... srcKeys) { public Response<Long> bitop(BitOP op, byte[] destKey, byte[]... srcKeys) {
client.bitop(op, destKey, srcKeys); client.bitop(op, destKey, srcKeys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<Long> bitop(BitOP op, String destKey, String... srcKeys) { public Response<Long> bitop(BitOP op, String destKey, String... srcKeys) {
client.bitop(op, destKey, srcKeys); client.bitop(op, destKey, srcKeys);
return getResponse(BuilderFactory.LONG); return getResponse(BuilderFactory.LONG);
} }
public Response<String> clusterNodes() { public Response<String> clusterNodes() {
@@ -425,23 +428,51 @@ abstract class MultiKeyPipelineBase extends PipelineBase implements
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<List<String>> clusterGetKeysInSlot(final int slot, final int count) { public Response<List<String>> clusterGetKeysInSlot(final int slot,
final int count) {
client.clusterGetKeysInSlot(slot, count); client.clusterGetKeysInSlot(slot, count);
return getResponse(BuilderFactory.STRING_LIST); return getResponse(BuilderFactory.STRING_LIST);
} }
public Response<String> clusterSetSlotNode(final int slot, final String nodeId) { public Response<String> clusterSetSlotNode(final int slot,
final String nodeId) {
client.clusterSetSlotNode(slot, nodeId); client.clusterSetSlotNode(slot, nodeId);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> clusterSetSlotMigrating(final int slot, final String nodeId) { public Response<String> clusterSetSlotMigrating(final int slot,
final String nodeId) {
client.clusterSetSlotMigrating(slot, nodeId); client.clusterSetSlotMigrating(slot, nodeId);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
public Response<String> clusterSetSlotImporting(final int slot, final String nodeId) { public Response<String> clusterSetSlotImporting(final int slot,
final String nodeId) {
client.clusterSetSlotImporting(slot, nodeId); client.clusterSetSlotImporting(slot, nodeId);
return getResponse(BuilderFactory.STRING); return getResponse(BuilderFactory.STRING);
} }
@Override
public Response<String> pfmerge(byte[] destkey, byte[]... sourcekeys) {
client.pfmerge(destkey, sourcekeys);
return getResponse(BuilderFactory.STRING);
}
@Override
public Response<String> pfmerge(String destkey, String... sourcekeys) {
client.pfmerge(destkey, sourcekeys);
return getResponse(BuilderFactory.STRING);
}
@Override
public Response<Long> pfcount(String...keys) {
client.pfcount(keys);
return getResponse(BuilderFactory.LONG);
}
@Override
public Response<Long> pfcount(final byte[] ... keys) {
client.pfcount(keys);
return getResponse(BuilderFactory.LONG);
}
} }

View File

@@ -1,66 +1,84 @@
package redis.clients.jedis; package redis.clients.jedis;
import redis.clients.jedis.exceptions.JedisDataException;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import redis.clients.jedis.exceptions.JedisDataException;
public class Pipeline extends MultiKeyPipelineBase { public class Pipeline extends MultiKeyPipelineBase {
private MultiResponseBuilder currentMulti; private MultiResponseBuilder currentMulti;
private class MultiResponseBuilder extends Builder<List<Object>>{ private class MultiResponseBuilder extends Builder<List<Object>> {
private List<Response<?>> responses = new ArrayList<Response<?>>(); private List<Response<?>> responses = new ArrayList<Response<?>>();
@Override @Override
public List<Object> build(Object data) { public List<Object> build(Object data) {
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Object> list = (List<Object>)data; List<Object> list = (List<Object>) data;
List<Object> values = new ArrayList<Object>(); List<Object> values = new ArrayList<Object>();
if(list.size() != responses.size()){ if (list.size() != responses.size()) {
throw new JedisDataException("Expected data size " + responses.size() + " but was " + list.size()); throw new JedisDataException("Expected data size "
} + responses.size() + " but was " + list.size());
}
for(int i=0;i<list.size();i++){ for (int i = 0; i < list.size(); i++) {
Response<?> response = responses.get(i); Response<?> response = responses.get(i);
response.set(list.get(i)); response.set(list.get(i));
values.add(response.get()); values.add(response.get());
} }
return values; return values;
} }
public void addResponse(Response<?> response){ public void setResponseDependency(Response<?> dependency) {
responses.add(response); for (Response<?> response : responses) {
} response.setDependency(dependency);
}
}
public void addResponse(Response<?> response) {
responses.add(response);
}
} }
@Override @Override
protected <T> Response<T> getResponse(Builder<T> builder) { protected <T> Response<T> getResponse(Builder<T> builder) {
if(currentMulti != null){ if (currentMulti != null) {
super.getResponse(BuilderFactory.STRING); //Expected QUEUED super.getResponse(BuilderFactory.STRING); // Expected QUEUED
Response<T> lr = new Response<T>(builder); Response<T> lr = new Response<T>(builder);
currentMulti.addResponse(lr); currentMulti.addResponse(lr);
return lr; return lr;
} } else {
else{ return super.getResponse(builder);
return super.getResponse(builder); }
}
} }
public void setClient(Client client) { public void setClient(Client client) {
this.client = client; this.client = client;
} }
@Override @Override
protected Client getClient(byte[] key) { protected Client getClient(byte[] key) {
return client; return client;
} }
@Override @Override
protected Client getClient(String key) { protected Client getClient(String key) {
return client; return client;
}
public void clear() {
if (isInMulti()) {
discard();
}
sync();
}
public boolean isInMulti() {
return currentMulti != null;
} }
/** /**
@@ -69,10 +87,10 @@ public class Pipeline extends MultiKeyPipelineBase {
* the different Response<?> of the commands you execute. * the different Response<?> of the commands you execute.
*/ */
public void sync() { public void sync() {
List<Object> unformatted = client.getMany(getPipelinedResponseLength()); List<Object> unformatted = client.getMany(getPipelinedResponseLength());
for (Object o : unformatted) {
for (Object resp : unformatted) generateResponse(o);
generateResponse(resp); }
} }
/** /**
@@ -84,33 +102,47 @@ public class Pipeline extends MultiKeyPipelineBase {
* @return A list of all the responses in the order you executed them. * @return A list of all the responses in the order you executed them.
*/ */
public List<Object> syncAndReturnAll() { public List<Object> syncAndReturnAll() {
List<Object> unformatted = client.getMany(getPipelinedResponseLength()); List<Object> unformatted = client.getMany(getPipelinedResponseLength());
List<Object> formatted = new ArrayList<Object>(); List<Object> formatted = new ArrayList<Object>();
for (Object resp : unformatted) for (Object o : unformatted) {
formatted.add(generateResponse(resp).get()); try {
formatted.add(generateResponse(o).get());
return formatted; } catch (JedisDataException e) {
formatted.add(e);
}
}
return formatted;
} }
public Response<String> discard() { public Response<String> discard() {
client.discard(); if (currentMulti == null)
currentMulti = null; throw new JedisDataException("DISCARD without MULTI");
return getResponse(BuilderFactory.STRING); client.discard();
currentMulti = null;
return getResponse(BuilderFactory.STRING);
} }
public Response<List<Object>> exec() { public Response<List<Object>> exec() {
client.exec(); if (currentMulti == null)
Response<List<Object>> response = super.getResponse(currentMulti); throw new JedisDataException("EXEC without MULTI");
currentMulti = null;
return response; client.exec();
Response<List<Object>> response = super.getResponse(currentMulti);
currentMulti.setResponseDependency(response);
currentMulti = null;
return response;
} }
public Response<String> multi() { public Response<String> multi() {
client.multi(); if (currentMulti != null)
Response<String> response = getResponse(BuilderFactory.STRING); //Expecting OK throw new JedisDataException("MULTI calls can not be nested");
currentMulti = new MultiResponseBuilder();
return response; client.multi();
Response<String> response = getResponse(BuilderFactory.STRING); // Expecting
// OK
currentMulti = new MultiResponseBuilder();
return response;
} }
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,6 +1,11 @@
package redis.clients.jedis; package redis.clients.jedis;
@Deprecated
/**
* This method is deprecated due to its error prone with multi
* and will be removed on next major release
* @see https://github.com/xetorthio/jedis/pull/498
*/
public abstract class PipelineBlock extends Pipeline { public abstract class PipelineBlock extends Pipeline {
// For shadowing // For shadowing
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@@ -5,6 +5,7 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
import redis.clients.jedis.exceptions.JedisAskDataException; import redis.clients.jedis.exceptions.JedisAskDataException;
import redis.clients.jedis.exceptions.JedisClusterException;
import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisMovedDataException; import redis.clients.jedis.exceptions.JedisMovedDataException;
@@ -16,7 +17,8 @@ public final class Protocol {
private static final String ASK_RESPONSE = "ASK"; private static final String ASK_RESPONSE = "ASK";
private static final String MOVED_RESPONSE = "MOVED"; private static final String MOVED_RESPONSE = "MOVED";
public static final int DEFAULT_PORT = 6379; private static final String CLUSTERDOWN_RESPONSE = "CLUSTERDOWN";
public static final int DEFAULT_PORT = 6379;
public static final int DEFAULT_SENTINEL_PORT = 26379; public static final int DEFAULT_SENTINEL_PORT = 26379;
public static final int DEFAULT_TIMEOUT = 2000; public static final int DEFAULT_TIMEOUT = 2000;
public static final int DEFAULT_DATABASE = 0; public static final int DEFAULT_DATABASE = 0;
@@ -33,6 +35,10 @@ public final class Protocol {
public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name"; public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name";
public static final String SENTINEL_RESET = "reset"; public static final String SENTINEL_RESET = "reset";
public static final String SENTINEL_SLAVES = "slaves"; public static final String SENTINEL_SLAVES = "slaves";
public static final String SENTINEL_FAILOVER = "failover";
public static final String SENTINEL_MONITOR = "monitor";
public static final String SENTINEL_REMOVE = "remove";
public static final String SENTINEL_SET = "set";
public static final String CLUSTER_NODES = "nodes"; public static final String CLUSTER_NODES = "nodes";
public static final String CLUSTER_MEET = "meet"; public static final String CLUSTER_MEET = "meet";
@@ -44,6 +50,18 @@ public final class Protocol {
public static final String CLUSTER_SETSLOT_NODE = "node"; public static final String CLUSTER_SETSLOT_NODE = "node";
public static final String CLUSTER_SETSLOT_MIGRATING = "migrating"; public static final String CLUSTER_SETSLOT_MIGRATING = "migrating";
public static final String CLUSTER_SETSLOT_IMPORTING = "importing"; public static final String CLUSTER_SETSLOT_IMPORTING = "importing";
public static final String CLUSTER_SETSLOT_STABLE = "stable";
public static final String CLUSTER_FORGET = "forget";
public static final String CLUSTER_FLUSHSLOT = "flushslots";
public static final String CLUSTER_KEYSLOT = "keyslot";
public static final String CLUSTER_COUNTKEYINSLOT = "countkeysinslot";
public static final String CLUSTER_SAVECONFIG = "saveconfig";
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 PUBSUB_CHANNELS= "channels";
public static final String PUBSUB_NUMSUB = "numsub";
public static final String PUBSUB_NUM_PAT = "numpat";
private Protocol() { private Protocol() {
// this prevent the class from instantiation // this prevent the class from instantiation
@@ -76,27 +94,34 @@ public final class Protocol {
} }
private static void processError(final RedisInputStream is) { private static void processError(final RedisInputStream is) {
String message = is.readLine(); String message = is.readLine();
//TODO: I'm not sure if this is the best way to do this. // TODO: I'm not sure if this is the best way to do this.
//Maybe Read only first 5 bytes instead? // Maybe Read only first 5 bytes instead?
if (message.startsWith(MOVED_RESPONSE)) { if (message.startsWith(MOVED_RESPONSE)) {
String[] movedInfo = parseTargetHostAndSlot(message); String[] movedInfo = parseTargetHostAndSlot(message);
throw new JedisMovedDataException(message, new HostAndPort(movedInfo[1], Integer.valueOf(movedInfo[2])), Integer.valueOf(movedInfo[0])); throw new JedisMovedDataException(message, new HostAndPort(
} else if (message.startsWith(ASK_RESPONSE)) { movedInfo[1], Integer.valueOf(movedInfo[2])),
String[] askInfo = parseTargetHostAndSlot(message); Integer.valueOf(movedInfo[0]));
throw new JedisAskDataException(message, new HostAndPort(askInfo[1], Integer.valueOf(askInfo[2])), Integer.valueOf(askInfo[0])); } else if (message.startsWith(ASK_RESPONSE)) {
} String[] askInfo = parseTargetHostAndSlot(message);
throw new JedisDataException(message); throw new JedisAskDataException(message, new HostAndPort(
askInfo[1], Integer.valueOf(askInfo[2])),
Integer.valueOf(askInfo[0]));
} else if (message.startsWith(CLUSTERDOWN_RESPONSE)) {
throw new JedisClusterException(message);
}
throw new JedisDataException(message);
} }
private static String[] parseTargetHostAndSlot(String clusterRedirectResponse) { private static String[] parseTargetHostAndSlot(
String[] response = new String[3]; String clusterRedirectResponse) {
String[] messageInfo = clusterRedirectResponse.split(" "); String[] response = new String[3];
String[] targetHostAndPort = messageInfo[2].split(":"); String[] messageInfo = clusterRedirectResponse.split(" ");
response[0] = messageInfo[1]; String[] targetHostAndPort = messageInfo[2].split(":");
response[1] = targetHostAndPort[0]; response[0] = messageInfo[1];
response[2] = targetHostAndPort[1]; response[1] = targetHostAndPort[0];
return response; response[2] = targetHostAndPort[1];
return response;
} }
private static Object process(final RedisInputStream is) { private static Object process(final RedisInputStream is) {
@@ -134,10 +159,11 @@ public final class Protocol {
int offset = 0; int offset = 0;
try { try {
while (offset < len) { while (offset < len) {
int size = is.read(read, offset, (len - offset)); int size = is.read(read, offset, (len - offset));
if (size == -1) if (size == -1)
throw new JedisConnectionException("It seems like server has closed the connection."); throw new JedisConnectionException(
offset += size; "It seems like server has closed the connection.");
offset += size;
} }
// read 2 more bytes for the command delimiter // read 2 more bytes for the command delimiter
is.readByte(); is.readByte();
@@ -191,7 +217,7 @@ public final class Protocol {
} }
public static enum Command { 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, 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, 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; 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;
public final byte[] raw; public final byte[] raw;
@@ -201,8 +227,7 @@ public final class Protocol {
} }
public static enum Keyword { public static enum Keyword {
AGGREGATE, ALPHA, ASC, BY, DESC, GET, LIMIT, MESSAGE, NO, NOSORT, PMESSAGE, PSUBSCRIBE, PUNSUBSCRIBE, OK, ONE, QUEUED, SET, STORE, SUBSCRIBE, UNSUBSCRIBE, WEIGHTS, WITHSCORES, RESETSTAT, RESET, FLUSH, EXISTS, LOAD, KILL, LEN, REFCOUNT, ENCODING, IDLETIME, AND, OR, XOR, NOT, AGGREGATE, ALPHA, ASC, BY, DESC, GET, LIMIT, MESSAGE, NO, NOSORT, PMESSAGE, PSUBSCRIBE, PUNSUBSCRIBE, OK, ONE, QUEUED, SET, STORE, SUBSCRIBE, UNSUBSCRIBE, WEIGHTS, WITHSCORES, RESETSTAT, RESET, FLUSH, EXISTS, LOAD, KILL, LEN, REFCOUNT, ENCODING, IDLETIME, AND, OR, XOR, NOT, GETNAME, SETNAME, LIST, MATCH, COUNT;
GETNAME, SETNAME,LIST, MATCH, COUNT;
public final byte[] raw; public final byte[] raw;
Keyword() { Keyword() {

View File

@@ -7,21 +7,21 @@ public class Queable {
private Queue<Response<?>> pipelinedResponses = new LinkedList<Response<?>>(); private Queue<Response<?>> pipelinedResponses = new LinkedList<Response<?>>();
protected void clean() { protected void clean() {
pipelinedResponses.clear(); pipelinedResponses.clear();
} }
protected Response<?> generateResponse(Object data) { protected Response<?> generateResponse(Object data) {
Response<?> response = pipelinedResponses.poll(); Response<?> response = pipelinedResponses.poll();
if (response != null) { if (response != null) {
response.set(data); response.set(data);
} }
return response; return response;
} }
protected <T> Response<T> getResponse(Builder<T> builder) { protected <T> Response<T> getResponse(Builder<T> builder) {
Response<T> lr = new Response<T>(builder); Response<T> lr = new Response<T>(builder);
pipelinedResponses.add(lr); pipelinedResponses.add(lr);
return lr; return lr;
} }
protected boolean hasPipelinedResponse() { protected boolean hasPipelinedResponse() {

View File

@@ -32,10 +32,7 @@ public interface RedisPipeline {
Response<Boolean> getbit(String key, long offset); Response<Boolean> getbit(String key, long offset);
Response<String> getrange(String key, long startOffset, long endOffset);
Response<String> getrange(String key, long startOffset,
long endOffset);
Response<String> getSet(String key, String value); Response<String> getSet(String key, String value);
@@ -70,7 +67,7 @@ public interface RedisPipeline {
Response<String> lindex(String key, long index); Response<String> lindex(String key, long index);
Response<Long> linsert(String key, BinaryClient.LIST_POSITION where, Response<Long> linsert(String key, BinaryClient.LIST_POSITION where,
String pivot, String value); String pivot, String value);
Response<Long> llen(String key); Response<Long> llen(String key);
@@ -118,8 +115,7 @@ public interface RedisPipeline {
Response<List<String>> sort(String key); Response<List<String>> sort(String key);
Response<List<String>> sort(String key, Response<List<String>> sort(String key, SortingParams sortingParameters);
SortingParams sortingParameters);
Response<String> spop(String key); Response<String> spop(String key);
@@ -145,35 +141,31 @@ public interface RedisPipeline {
Response<Set<String>> zrange(String key, long start, long end); Response<Set<String>> zrange(String key, long start, long end);
Response<Set<String>> zrangeByScore(String key, double min, Response<Set<String>> zrangeByScore(String key, double min, double max);
double max);
Response<Set<String>> zrangeByScore(String key, String min, Response<Set<String>> zrangeByScore(String key, String min, String max);
String max);
Response<Set<String>> zrangeByScore(String key, double min, Response<Set<String>> zrangeByScore(String key, double min, double max,
double max, int offset, int count); int offset, int count);
Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min,
double max); double max);
Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min, Response<Set<Tuple>> zrangeByScoreWithScores(String key, double min,
double max, int offset, int count); double max, int offset, int count);
Response<Set<String>> zrevrangeByScore(String key, double max, Response<Set<String>> zrevrangeByScore(String key, double max, double min);
double min);
Response<Set<String>> zrevrangeByScore(String key, String max, Response<Set<String>> zrevrangeByScore(String key, String max, String min);
String min);
Response<Set<String>> zrevrangeByScore(String key, double max, Response<Set<String>> zrevrangeByScore(String key, double max, double min,
double min, int offset, int count); int offset, int count);
Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max,
double max, double min); double min);
Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, Response<Set<Tuple>> zrevrangeByScoreWithScores(String key, double max,
double max, double min, int offset, int count); double min, int offset, int count);
Response<Set<Tuple>> zrangeWithScores(String key, long start, long end); Response<Set<Tuple>> zrangeWithScores(String key, long start, long end);
@@ -187,8 +179,7 @@ public interface RedisPipeline {
Response<Set<String>> zrevrange(String key, long start, long end); Response<Set<String>> zrevrange(String key, long start, long end);
Response<Set<Tuple>> zrevrangeWithScores(String key, long start, Response<Set<Tuple>> zrevrangeWithScores(String key, long start, long end);
long end);
Response<Long> zrevrank(String key, String member); Response<Long> zrevrank(String key, String member);
@@ -197,4 +188,8 @@ public interface RedisPipeline {
Response<Long> bitcount(String key); Response<Long> bitcount(String key);
Response<Long> bitcount(String key, long start, long end); Response<Long> bitcount(String key, long start, long end);
Response<Long> pfadd(final String key, final String... elements);
Response<Long> pfcount(final String key);
} }

View File

@@ -8,36 +8,54 @@ public class Response<T> {
private boolean set = false; private boolean set = false;
private Builder<T> builder; private Builder<T> builder;
private Object data; private Object data;
private Response<?> dependency = null;
private boolean requestDependencyBuild = false;
public Response(Builder<T> b) { public Response(Builder<T> b) {
this.builder = b; this.builder = b;
} }
public void set(Object data) { public void set(Object data) {
this.data = data; this.data = data;
set = true; set = true;
} }
public T get() { public T get() {
if (!set) { // if response has dependency response and dependency is not built,
throw new JedisDataException( // build it first and no more!!
"Please close pipeline or multi block before calling this method."); if (!requestDependencyBuild && dependency != null && dependency.set
} && !dependency.built) {
if (!built) { requestDependencyBuild = true;
if(data != null ){ dependency.build();
if (data instanceof JedisDataException){ }
throw new JedisDataException((JedisDataException)data); if (!set) {
} throw new JedisDataException(
response = builder.build(data); "Please close pipeline or multi block before calling this method.");
} }
this.data = null; if (!built) {
built = true; build();
} }
return response; return response;
}
public void setDependency(Response<?> dependency) {
this.dependency = dependency;
this.requestDependencyBuild = false;
}
private void build() {
if (data != null) {
if (data instanceof JedisDataException) {
throw new JedisDataException((JedisDataException) data);
}
response = builder.build(data);
}
data = null;
built = true;
} }
public String toString() { public String toString() {
return "Response " + builder.toString(); return "Response " + builder.toString();
} }
} }

View File

@@ -12,15 +12,25 @@ import redis.clients.util.SafeEncoder;
public class ScanParams { public class ScanParams {
private List<byte[]> params = new ArrayList<byte[]>(); private List<byte[]> params = new ArrayList<byte[]>();
public final static String SCAN_POINTER_START = String.valueOf(0);
public final static byte[] SCAN_POINTER_START_BINARY = SafeEncoder.encode(SCAN_POINTER_START);
public void match(final String pattern) { public ScanParams match(final byte[] pattern) {
params.add(MATCH.raw); params.add(MATCH.raw);
params.add(SafeEncoder.encode(pattern)); params.add(pattern);
return this;
} }
public void count(final int count) { public ScanParams match(final String pattern) {
params.add(MATCH.raw);
params.add(SafeEncoder.encode(pattern));
return this;
}
public ScanParams count(final int count) {
params.add(COUNT.raw); params.add(COUNT.raw);
params.add(Protocol.toByteArray(count)); params.add(Protocol.toByteArray(count));
return this;
} }
public Collection<byte[]> getParams() { public Collection<byte[]> getParams() {

View File

@@ -2,16 +2,50 @@ package redis.clients.jedis;
import java.util.List; import java.util.List;
import redis.clients.util.SafeEncoder;
public class ScanResult<T> { public class ScanResult<T> {
private int cursor; private byte[] cursor;
private List<T> results; 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) { public ScanResult(int cursor, List<T> results) {
this(Protocol.toByteArray(cursor), results);
}
public ScanResult(String cursor, List<T> results) {
this(SafeEncoder.encode(cursor), results);
}
public ScanResult(byte[] cursor, List<T> results) {
this.cursor = cursor; this.cursor = cursor;
this.results = results; 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() { public int getCursor() {
return Integer.parseInt(getStringCursor());
}
/**
* FIXME: This method should be changed to getCursor() on next major release
*/
public String getStringCursor() {
return SafeEncoder.encode(cursor);
}
public byte[] getCursorAsBytes() {
return cursor; return cursor;
} }

View File

@@ -0,0 +1,22 @@
package redis.clients.jedis;
import java.util.List;
import java.util.Map;
public interface SentinelCommands {
public List<Map<String, String>> sentinelMasters();
public List<String> sentinelGetMasterAddrByName(String masterName);
public Long sentinelReset(String pattern);
public List<Map<String, String>> sentinelSlaves(String masterName);
public String sentinelFailover(String masterName);
public String sentinelMonitor(String masterName, String ip, int port, int quorum);
public String sentinelRemove(String masterName);
public String sentinelSet(String masterName, Map<String, String> parameterMap);
}

View File

@@ -1,5 +1,6 @@
package redis.clients.jedis; package redis.clients.jedis;
import java.io.Closeable;
import redis.clients.jedis.BinaryClient.LIST_POSITION; import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.util.Hashing; import redis.clients.util.Hashing;
@@ -9,7 +10,13 @@ import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
import java.util.regex.Pattern; import java.util.regex.Pattern;
public class ShardedJedis extends BinaryShardedJedis implements JedisCommands { import redis.clients.util.Pool;
public class ShardedJedis extends BinaryShardedJedis implements JedisCommands,
Closeable {
protected Pool<ShardedJedis> dataSource = null;
public ShardedJedis(List<JedisShardInfo> shards) { public ShardedJedis(List<JedisShardInfo> shards) {
super(shards); super(shards);
} }
@@ -32,14 +39,21 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
return j.set(key, value); return j.set(key, value);
} }
@Override
public String set(String key, String value, String nxxx, String expx,
long time) {
Jedis j = getShard(key);
return j.set(key, value, nxxx, expx, time);
}
public String get(String key) { public String get(String key) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.get(key); return j.get(key);
} }
public String echo(String string) { public String echo(String string) {
Jedis j = getShard(string); Jedis j = getShard(string);
return j.echo(string); return j.echo(string);
} }
public Boolean exists(String key) { public Boolean exists(String key) {
@@ -73,8 +87,8 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
} }
public Boolean setbit(String key, long offset, String value) { public Boolean setbit(String key, long offset, String value) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.setbit(key, offset, value); return j.setbit(key, offset, value);
} }
public Boolean getbit(String key, long offset) { public Boolean getbit(String key, long offset) {
@@ -108,13 +122,13 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
} }
public List<String> blpop(String arg) { public List<String> blpop(String arg) {
Jedis j = getShard(arg); Jedis j = getShard(arg);
return j.blpop(arg); return j.blpop(arg);
} }
public List<String> brpop(String arg) { public List<String> brpop(String arg) {
Jedis j = getShard(arg); Jedis j = getShard(arg);
return j.brpop(arg); return j.brpop(arg);
} }
public Long decrBy(String key, long integer) { public Long decrBy(String key, long integer) {
@@ -132,6 +146,11 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
return j.incrBy(key, integer); return j.incrBy(key, integer);
} }
public Double incrByFloat(String key, double integer) {
Jedis j = getShard(key);
return j.incrByFloat(key, integer);
}
public Long incr(String key) { public Long incr(String key) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.incr(key); return j.incr(key);
@@ -177,6 +196,11 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
return j.hincrBy(key, field, value); return j.hincrBy(key, field, value);
} }
public Double hincrByFloat(String key, String field, double value) {
Jedis j = getShard(key);
return j.hincrByFloat(key, field, value);
}
public Boolean hexists(String key, String field) { public Boolean hexists(String key, String field) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.hexists(key, field); return j.hexists(key, field);
@@ -228,13 +252,13 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
} }
public Long strlen(final String key) { public Long strlen(final String key) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.strlen(key); return j.strlen(key);
} }
public Long move(String key, int dbIndex) { public Long move(String key, int dbIndex) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.move(key, dbIndex); return j.move(key, dbIndex);
} }
public Long rpushx(String key, String... string) { public Long rpushx(String key, String... string) {
@@ -243,8 +267,8 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
} }
public Long persist(final String key) { public Long persist(final String key) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.persist(key); return j.persist(key);
} }
public Long llen(String key) { public Long llen(String key) {
@@ -327,7 +351,7 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
return j.zadd(key, score, member); return j.zadd(key, score, member);
} }
public Long zadd(String key, Map<Double, String> scoreMembers) { public Long zadd(String key, Map<String, Double> scoreMembers) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.zadd(key, scoreMembers); return j.zadd(key, scoreMembers);
} }
@@ -523,18 +547,96 @@ public class ShardedJedis extends BinaryShardedJedis implements JedisCommands {
return j.bitcount(key, start, end); 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) { public ScanResult<Entry<String, String>> hscan(String key, int cursor) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.hscan(key, cursor); 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) { public ScanResult<String> sscan(String key, int cursor) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.sscan(key, cursor); 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) { public ScanResult<Tuple> zscan(String key, int cursor) {
Jedis j = getShard(key); Jedis j = getShard(key);
return j.zscan(key, cursor); return j.zscan(key, cursor);
} }
public ScanResult<Entry<String, String>> hscan(String key,
final String cursor) {
Jedis j = getShard(key);
return j.hscan(key, cursor);
}
public ScanResult<String> sscan(String key, final String cursor) {
Jedis j = getShard(key);
return j.sscan(key, cursor);
}
public ScanResult<Tuple> zscan(String key, final String cursor) {
Jedis j = getShard(key);
return j.zscan(key, cursor);
}
@Override
public void close() {
if (dataSource != null) {
boolean broken = false;
for (Jedis jedis : getAllShards()) {
if (jedis.getClient().isBroken()) {
broken = true;
}
}
if (broken) {
dataSource.returnBrokenResource(this);
} else {
this.resetState();
dataSource.returnResource(this);
}
} else {
disconnect();
}
}
public void setDataSource(Pool<ShardedJedis> shardedJedisPool) {
this.dataSource = shardedJedisPool;
}
public void resetState() {
for (Jedis jedis : getAllShards()) {
jedis.resetState();
}
}
public Long pfadd(String key, String... elements) {
Jedis j = getShard(key);
return j.pfadd(key, elements);
}
@Override
public long pfcount(String key) {
Jedis j = getShard(key);
return j.pfcount(key);
}
} }

View File

@@ -11,27 +11,27 @@ public class ShardedJedisPipeline extends PipelineBase {
private Queue<Client> clients = new LinkedList<Client>(); private Queue<Client> clients = new LinkedList<Client>();
private static class FutureResult { private static class FutureResult {
private Client client; private Client client;
public FutureResult(Client client) { public FutureResult(Client client) {
this.client = client; this.client = client;
} }
public Object get() { public Object get() {
return client.getOne(); return client.getOne();
} }
} }
public void setShardedJedis(BinaryShardedJedis jedis) { public void setShardedJedis(BinaryShardedJedis jedis) {
this.jedis = jedis; this.jedis = jedis;
} }
public List<Object> getResults() { public List<Object> getResults() {
List<Object> r = new ArrayList<Object>(); List<Object> r = new ArrayList<Object>();
for (FutureResult fr : results) { for (FutureResult fr : results) {
r.add(fr.get()); r.add(fr.get());
} }
return r; return r;
} }
/** /**
@@ -40,30 +40,30 @@ public class ShardedJedisPipeline extends PipelineBase {
* the different Response&lt;?&gt; of the commands you execute. * the different Response&lt;?&gt; of the commands you execute.
*/ */
public void sync() { public void sync() {
for (Client client : clients) { for (Client client : clients) {
generateResponse(client.getOne()); generateResponse(client.getOne());
} }
} }
/** /**
* Syncronize pipeline by reading all responses. This operation closes the * Syncronize pipeline by reading all responses. This operation closes the
* pipeline. Whenever possible try to avoid using this version and use * pipeline. Whenever possible try to avoid using this version and use
* ShardedJedisPipeline.sync() as it won't go through all the responses and generate the * ShardedJedisPipeline.sync() as it won't go through all the responses and
* right response type (usually it is a waste of time). * generate the right response type (usually it is a waste of time).
* *
* @return A list of all the responses in the order you executed them. * @return A list of all the responses in the order you executed them.
*/ */
public List<Object> syncAndReturnAll() { public List<Object> syncAndReturnAll() {
List<Object> formatted = new ArrayList<Object>(); List<Object> formatted = new ArrayList<Object>();
for (Client client : clients) { for (Client client : clients) {
formatted.add(generateResponse(client.getOne()).get()); formatted.add(generateResponse(client.getOne()).get());
} }
return formatted; return formatted;
} }
/** /**
* This method will be removed in Jedis 3.0. Use the methods that return Response's and call * This method will be removed in Jedis 3.0. Use the methods that return
* sync(). * Response's and call sync().
*/ */
@Deprecated @Deprecated
public void execute() { public void execute() {
@@ -71,17 +71,17 @@ public class ShardedJedisPipeline extends PipelineBase {
@Override @Override
protected Client getClient(String key) { protected Client getClient(String key) {
Client client = jedis.getShard(key).getClient(); Client client = jedis.getShard(key).getClient();
clients.add(client); clients.add(client);
results.add(new FutureResult(client)); results.add(new FutureResult(client));
return client; return client;
} }
@Override @Override
protected Client getClient(byte[] key) { protected Client getClient(byte[] key) {
Client client = jedis.getShard(key).getClient(); Client client = jedis.getShard(key).getClient();
clients.add(client); clients.add(client);
results.add(new FutureResult(client)); results.add(new FutureResult(client));
return client; return client;
} }
} }

View File

@@ -32,6 +32,28 @@ public class ShardedJedisPool extends Pool<ShardedJedis> {
super(poolConfig, new ShardedJedisFactory(shards, algo, keyTagPattern)); super(poolConfig, new ShardedJedisFactory(shards, algo, keyTagPattern));
} }
@Override
public ShardedJedis getResource() {
ShardedJedis jedis = super.getResource();
jedis.setDataSource(this);
return jedis;
}
@Override
public void returnBrokenResource(final ShardedJedis resource) {
if (resource != null) {
returnBrokenResourceObject(resource);
}
}
@Override
public void returnResource(final ShardedJedis resource) {
if (resource != null) {
resource.resetState();
returnResourceObject(resource);
}
}
/** /**
* PoolableObjectFactory custom impl. * PoolableObjectFactory custom impl.
*/ */

View File

@@ -36,7 +36,7 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams by(final String pattern) { public SortingParams by(final String pattern) {
return by(SafeEncoder.encode(pattern)); return by(SafeEncoder.encode(pattern));
} }
/** /**
@@ -53,9 +53,9 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams by(final byte[] pattern) { public SortingParams by(final byte[] pattern) {
params.add(BY.raw); params.add(BY.raw);
params.add(pattern); params.add(pattern);
return this; return this;
} }
/** /**
@@ -67,13 +67,13 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams nosort() { public SortingParams nosort() {
params.add(BY.raw); params.add(BY.raw);
params.add(NOSORT.raw); params.add(NOSORT.raw);
return this; return this;
} }
public Collection<byte[]> getParams() { public Collection<byte[]> getParams() {
return Collections.unmodifiableCollection(params); return Collections.unmodifiableCollection(params);
} }
/** /**
@@ -82,8 +82,8 @@ public class SortingParams {
* @return the sortingParams Object * @return the sortingParams Object
*/ */
public SortingParams desc() { public SortingParams desc() {
params.add(DESC.raw); params.add(DESC.raw);
return this; return this;
} }
/** /**
@@ -92,8 +92,8 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams asc() { public SortingParams asc() {
params.add(ASC.raw); params.add(ASC.raw);
return this; return this;
} }
/** /**
@@ -105,10 +105,10 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams limit(final int start, final int count) { public SortingParams limit(final int start, final int count) {
params.add(LIMIT.raw); params.add(LIMIT.raw);
params.add(Protocol.toByteArray(start)); params.add(Protocol.toByteArray(start));
params.add(Protocol.toByteArray(count)); params.add(Protocol.toByteArray(count));
return this; return this;
} }
/** /**
@@ -118,8 +118,8 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams alpha() { public SortingParams alpha() {
params.add(ALPHA.raw); params.add(ALPHA.raw);
return this; return this;
} }
/** /**
@@ -138,11 +138,11 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams get(String... patterns) { public SortingParams get(String... patterns) {
for (final String pattern : patterns) { for (final String pattern : patterns) {
params.add(GET.raw); params.add(GET.raw);
params.add(SafeEncoder.encode(pattern)); params.add(SafeEncoder.encode(pattern));
} }
return this; return this;
} }
/** /**
@@ -161,10 +161,10 @@ public class SortingParams {
* @return the SortingParams Object * @return the SortingParams Object
*/ */
public SortingParams get(byte[]... patterns) { public SortingParams get(byte[]... patterns) {
for (final byte[] pattern : patterns) { for (final byte[] pattern : patterns) {
params.add(GET.raw); params.add(GET.raw);
params.add(pattern); params.add(pattern);
} }
return this; return this;
} }
} }

View File

@@ -6,78 +6,83 @@ import java.util.List;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
/** /**
* Transaction is nearly identical to Pipeline, only differences are the multi/discard behaviors * Transaction is nearly identical to Pipeline, only differences are the
* multi/discard behaviors
*/ */
public class Transaction extends MultiKeyPipelineBase { public class Transaction extends MultiKeyPipelineBase {
protected boolean inTransaction = true; protected boolean inTransaction = true;
protected Transaction(){ protected Transaction() {
// client will be set later in transaction block // client will be set later in transaction block
} }
public Transaction(final Client client) { public Transaction(final Client client) {
this.client = client; this.client = client;
} }
@Override @Override
protected Client getClient(String key) { protected Client getClient(String key) {
return client; return client;
} }
@Override @Override
protected Client getClient(byte[] key) { protected Client getClient(byte[] key) {
return client; return client;
}
public void clear() {
if (inTransaction) {
discard();
}
} }
public List<Object> exec() { public List<Object> exec() {
// Discard QUEUED or ERROR // Discard QUEUED or ERROR
client.getMany(getPipelinedResponseLength()); client.getMany(getPipelinedResponseLength());
client.exec();
client.exec(); List<Object> unformatted = client.getObjectMultiBulkReply();
if (unformatted == null) {
List<Object> unformatted = client.getObjectMultiBulkReply(); return null;
if (unformatted == null) { }
return null; List<Object> formatted = new ArrayList<Object>();
} for (Object o : unformatted) {
List<Object> formatted = new ArrayList<Object>(); try {
for (Object o : unformatted) { formatted.add(generateResponse(o).get());
try { } catch (JedisDataException e) {
formatted.add(generateResponse(o).get()); formatted.add(e);
} catch (JedisDataException e) { }
formatted.add(e); }
} return formatted;
}
return formatted;
} }
public List<Response<?>> execGetResponse() { public List<Response<?>> execGetResponse() {
// Discard QUEUED or ERROR // Discard QUEUED or ERROR
client.getMany(getPipelinedResponseLength()); client.getMany(getPipelinedResponseLength());
client.exec();
client.exec(); List<Object> unformatted = client.getObjectMultiBulkReply();
if (unformatted == null) {
List<Object> unformatted = client.getObjectMultiBulkReply(); return null;
if (unformatted == null) { }
return null; List<Response<?>> response = new ArrayList<Response<?>>();
} for (Object o : unformatted) {
List<Response<?>> response = new ArrayList<Response<?>>(); response.add(generateResponse(o));
for (Object o : unformatted) { }
response.add(generateResponse(o)); return response;
}
return response;
} }
public String discard() { public String discard() {
client.getMany(getPipelinedResponseLength()); client.getMany(getPipelinedResponseLength());
client.discard(); client.discard();
inTransaction = false; inTransaction = false;
clean(); clean();
return client.getStatusCodeReply(); return client.getStatusCodeReply();
} }
public void setClient(Client client) { public void setClient(Client client) {
this.client = client; this.client = client;
} }
} }

View File

@@ -2,6 +2,12 @@ package redis.clients.jedis;
import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.exceptions.JedisException;
@Deprecated
/**
* This class is deprecated due to its error prone
* and will be removed on next major release
* @see https://github.com/xetorthio/jedis/pull/498
*/
public abstract class TransactionBlock extends Transaction { public abstract class TransactionBlock extends Transaction {
// For shadowing // For shadowing
@SuppressWarnings("unused") @SuppressWarnings("unused")

View File

@@ -9,72 +9,72 @@ public class Tuple implements Comparable<Tuple> {
private Double score; private Double score;
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;
int result = 1; int result = 1;
result = prime * result; result = prime * result;
if (null != element) { if (null != element) {
for (final byte b : element) { for (final byte b : element) {
result = prime * result + b; result = prime * result + b;
} }
} }
long temp; long temp;
temp = Double.doubleToLongBits(score); temp = Double.doubleToLongBits(score);
result = prime * result + (int) (temp ^ (temp >>> 32)); result = prime * result + (int) (temp ^ (temp >>> 32));
return result; return result;
} }
public boolean equals(Object obj) { public boolean equals(Object obj) {
if (this == obj) if (this == obj)
return true; return true;
if (obj == null) if (obj == null)
return false; return false;
if (getClass() != obj.getClass()) if (getClass() != obj.getClass())
return false; return false;
Tuple other = (Tuple) obj; Tuple other = (Tuple) obj;
if (element == null) { if (element == null) {
if (other.element != null) if (other.element != null)
return false; return false;
} else if (!Arrays.equals(element, other.element)) } else if (!Arrays.equals(element, other.element))
return false; return false;
return true; return true;
} }
public int compareTo(Tuple other) { public int compareTo(Tuple other) {
if (Arrays.equals(this.element, other.element)) if (Arrays.equals(this.element, other.element))
return 0; return 0;
else else
return this.score < other.getScore() ? -1 : 1; return this.score < other.getScore() ? -1 : 1;
} }
public Tuple(String element, Double score) { public Tuple(String element, Double score) {
super(); super();
this.element = SafeEncoder.encode(element); this.element = SafeEncoder.encode(element);
this.score = score; this.score = score;
} }
public Tuple(byte[] element, Double score) { public Tuple(byte[] element, Double score) {
super(); super();
this.element = element; this.element = element;
this.score = score; this.score = score;
} }
public String getElement() { public String getElement() {
if (null != element) { if (null != element) {
return SafeEncoder.encode(element); return SafeEncoder.encode(element);
} else { } else {
return null; return null;
} }
} }
public byte[] getBinaryElement() { public byte[] getBinaryElement() {
return element; return element;
} }
public double getScore() { public double getScore() {
return score; return score;
} }
public String toString() { public String toString() {
return '[' + Arrays.toString(element) + ',' + score + ']'; return '[' + Arrays.toString(element) + ',' + score + ']';
} }
} }

View File

@@ -12,33 +12,33 @@ import redis.clients.util.SafeEncoder;
public class ZParams { public class ZParams {
public enum Aggregate { public enum Aggregate {
SUM, MIN, MAX; SUM, MIN, MAX;
public final byte[] raw; public final byte[] raw;
Aggregate() { Aggregate() {
raw = SafeEncoder.encode(name()); raw = SafeEncoder.encode(name());
} }
} }
private List<byte[]> params = new ArrayList<byte[]>(); private List<byte[]> params = new ArrayList<byte[]>();
public ZParams weights(final int... weights) { public ZParams weights(final int... weights) {
params.add(WEIGHTS.raw); params.add(WEIGHTS.raw);
for (final int weight : weights) { for (final int weight : weights) {
params.add(Protocol.toByteArray(weight)); params.add(Protocol.toByteArray(weight));
} }
return this; return this;
} }
public Collection<byte[]> getParams() { public Collection<byte[]> getParams() {
return Collections.unmodifiableCollection(params); return Collections.unmodifiableCollection(params);
} }
public ZParams aggregate(final Aggregate aggregate) { public ZParams aggregate(final Aggregate aggregate) {
params.add(AGGREGATE.raw); params.add(AGGREGATE.raw);
params.add(aggregate.raw); params.add(aggregate.raw);
return this; return this;
} }
} }

View File

@@ -5,16 +5,19 @@ import redis.clients.jedis.HostAndPort;
public class JedisAskDataException extends JedisRedirectionException { public class JedisAskDataException extends JedisRedirectionException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisAskDataException(Throwable cause, HostAndPort targetHost, int slot) { public JedisAskDataException(Throwable cause, HostAndPort targetHost,
super(cause, targetHost, slot); int slot) {
super(cause, targetHost, slot);
} }
public JedisAskDataException(String message, Throwable cause, HostAndPort targetHost, int slot) { public JedisAskDataException(String message, Throwable cause,
super(message, cause, targetHost, slot); HostAndPort targetHost, int slot) {
super(message, cause, targetHost, slot);
} }
public JedisAskDataException(String message, HostAndPort targetHost, int slot) { public JedisAskDataException(String message, HostAndPort targetHost,
super(message, targetHost, slot); int slot) {
} super(message, targetHost, slot);
}
} }

View File

@@ -1,18 +1,17 @@
package redis.clients.jedis.exceptions; package redis.clients.jedis.exceptions;
public class JedisClusterException extends JedisDataException { public class JedisClusterException extends JedisDataException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisClusterException(Throwable cause) { public JedisClusterException(Throwable cause) {
super(cause); super(cause);
} }
public JedisClusterException(String message, Throwable cause) { public JedisClusterException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
public JedisClusterException(String message) { public JedisClusterException(String message) {
super(message); super(message);
} }
} }

View File

@@ -1,18 +1,17 @@
package redis.clients.jedis.exceptions; package redis.clients.jedis.exceptions;
public class JedisClusterMaxRedirectionsException extends JedisDataException { public class JedisClusterMaxRedirectionsException extends JedisDataException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisClusterMaxRedirectionsException(Throwable cause) { public JedisClusterMaxRedirectionsException(Throwable cause) {
super(cause); super(cause);
} }
public JedisClusterMaxRedirectionsException(String message, Throwable cause) { public JedisClusterMaxRedirectionsException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
public JedisClusterMaxRedirectionsException(String message) { public JedisClusterMaxRedirectionsException(String message) {
super(message); super(message);
} }
} }

View File

@@ -4,14 +4,14 @@ public class JedisConnectionException extends JedisException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisConnectionException(String message) { public JedisConnectionException(String message) {
super(message); super(message);
} }
public JedisConnectionException(Throwable cause) { public JedisConnectionException(Throwable cause) {
super(cause); super(cause);
} }
public JedisConnectionException(String message, Throwable cause) { public JedisConnectionException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }

View File

@@ -4,14 +4,14 @@ public class JedisDataException extends JedisException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisDataException(String message) { public JedisDataException(String message) {
super(message); super(message);
} }
public JedisDataException(Throwable cause) { public JedisDataException(Throwable cause) {
super(cause); super(cause);
} }
public JedisDataException(String message, Throwable cause) { public JedisDataException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }

View File

@@ -1,18 +1,17 @@
package redis.clients.jedis.exceptions; package redis.clients.jedis.exceptions;
public class JedisException extends RuntimeException { public class JedisException extends RuntimeException {
private static final long serialVersionUID = -2946266495682282677L; private static final long serialVersionUID = -2946266495682282677L;
public JedisException(String message) { public JedisException(String message) {
super(message); super(message);
} }
public JedisException(Throwable e) { public JedisException(Throwable e) {
super(e); super(e);
} }
public JedisException(String message, Throwable cause) { public JedisException(String message, Throwable cause) {
super(message, cause); super(message, cause);
} }
} }

View File

@@ -2,20 +2,21 @@ package redis.clients.jedis.exceptions;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
public class JedisMovedDataException extends JedisRedirectionException { public class JedisMovedDataException extends JedisRedirectionException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
public JedisMovedDataException(String message, HostAndPort targetNode,
public JedisMovedDataException(String message, HostAndPort targetNode, int slot) { int slot) {
super(message, targetNode, slot); super(message, targetNode, slot);
} }
public JedisMovedDataException(Throwable cause, HostAndPort targetNode, int slot) { public JedisMovedDataException(Throwable cause, HostAndPort targetNode,
super(cause, targetNode, slot); int slot) {
super(cause, targetNode, slot);
} }
public JedisMovedDataException(String message, Throwable cause, HostAndPort targetNode, int slot) { public JedisMovedDataException(String message, Throwable cause,
super(message, cause, targetNode, slot); HostAndPort targetNode, int slot) {
super(message, cause, targetNode, slot);
} }
} }

View File

@@ -2,36 +2,38 @@ package redis.clients.jedis.exceptions;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
public class JedisRedirectionException extends JedisDataException { public class JedisRedirectionException extends JedisDataException {
private static final long serialVersionUID = 3878126572474819403L; private static final long serialVersionUID = 3878126572474819403L;
private HostAndPort targetNode; private HostAndPort targetNode;
private int slot; private int slot;
public JedisRedirectionException(String message, HostAndPort targetNode, int slot) { public JedisRedirectionException(String message, HostAndPort targetNode,
super(message); int slot) {
this.targetNode = targetNode; super(message);
this.slot = slot; this.targetNode = targetNode;
this.slot = slot;
} }
public JedisRedirectionException(Throwable cause, HostAndPort targetNode, int slot) { public JedisRedirectionException(Throwable cause, HostAndPort targetNode,
super(cause); int slot) {
this.targetNode = targetNode; super(cause);
this.slot = slot; this.targetNode = targetNode;
this.slot = slot;
} }
public JedisRedirectionException(String message, Throwable cause, HostAndPort targetNode, int slot) { public JedisRedirectionException(String message, Throwable cause,
super(message, cause); HostAndPort targetNode, int slot) {
this.targetNode = targetNode; super(message, cause);
this.slot = slot; this.targetNode = targetNode;
this.slot = slot;
} }
public HostAndPort getTargetNode() { public HostAndPort getTargetNode() {
return targetNode; return targetNode;
} }
public int getSlot() { public int getSlot() {
return slot; return slot;
} }
} }

View File

@@ -0,0 +1,48 @@
package redis.clients.util;
import redis.clients.jedis.HostAndPort;
import java.util.ArrayList;
import java.util.List;
public class ClusterNodeInformation {
private HostAndPort node;
private List<Integer> availableSlots;
private List<Integer> slotsBeingImported;
private List<Integer> slotsBeingMigrated;
public ClusterNodeInformation(HostAndPort node) {
this.node = node;
this.availableSlots = new ArrayList<Integer>();
this.slotsBeingImported = new ArrayList<Integer>();
this.slotsBeingMigrated = new ArrayList<Integer>();
}
public void addAvailableSlot(int slot) {
availableSlots.add(slot);
}
public void addSlotBeingImported(int slot) {
slotsBeingImported.add(slot);
}
public void addSlotBeingMigrated(int slot) {
slotsBeingMigrated.add(slot);
}
public HostAndPort getNode() {
return node;
}
public List<Integer> getAvailableSlots() {
return availableSlots;
}
public List<Integer> getSlotsBeingImported() {
return slotsBeingImported;
}
public List<Integer> getSlotsBeingMigrated() {
return slotsBeingMigrated;
}
}

View File

@@ -0,0 +1,80 @@
package redis.clients.util;
import redis.clients.jedis.HostAndPort;
public class ClusterNodeInformationParser {
private static final String SLOT_IMPORT_IDENTIFIER = "-<-";
private static final String SLOT_IN_TRANSITION_IDENTIFIER = "[";
public static final int SLOT_INFORMATIONS_START_INDEX = 8;
public static final int HOST_AND_PORT_INDEX = 1;
public ClusterNodeInformation parse(String nodeInfo, HostAndPort current) {
String[] nodeInfoPartArray = nodeInfo.split(" ");
HostAndPort node = getHostAndPortFromNodeLine(nodeInfoPartArray,
current);
ClusterNodeInformation info = new ClusterNodeInformation(node);
if (nodeInfoPartArray.length >= SLOT_INFORMATIONS_START_INDEX) {
String[] slotInfoPartArray = extractSlotParts(nodeInfoPartArray);
fillSlotInformation(slotInfoPartArray, info);
}
return info;
}
private String[] extractSlotParts(String[] nodeInfoPartArray) {
String[] slotInfoPartArray = new String[nodeInfoPartArray.length
- SLOT_INFORMATIONS_START_INDEX];
for (int i = SLOT_INFORMATIONS_START_INDEX; i < nodeInfoPartArray.length; i++) {
slotInfoPartArray[i - SLOT_INFORMATIONS_START_INDEX] = nodeInfoPartArray[i];
}
return slotInfoPartArray;
}
public HostAndPort getHostAndPortFromNodeLine(String[] nodeInfoPartArray,
HostAndPort current) {
String stringHostAndPort = nodeInfoPartArray[HOST_AND_PORT_INDEX];
String[] arrayHostAndPort = stringHostAndPort.split(":");
return new HostAndPort(
arrayHostAndPort[0].isEmpty() ? current.getHost()
: arrayHostAndPort[0],
arrayHostAndPort[1].isEmpty() ? current.getPort() : Integer
.valueOf(arrayHostAndPort[1]));
}
private void fillSlotInformation(String[] slotInfoPartArray,
ClusterNodeInformation info) {
for (String slotRange : slotInfoPartArray) {
fillSlotInformationFromSlotRange(slotRange, info);
}
}
private void fillSlotInformationFromSlotRange(String slotRange,
ClusterNodeInformation info) {
if (slotRange.startsWith(SLOT_IN_TRANSITION_IDENTIFIER)) {
// slot is in transition
int slot = Integer.parseInt(slotRange.substring(1).split("-")[0]);
if (slotRange.contains(SLOT_IMPORT_IDENTIFIER)) {
// import
info.addSlotBeingImported(slot);
} else {
// migrate (->-)
info.addSlotBeingMigrated(slot);
}
} else if (slotRange.contains("-")) {
// slot range
String[] slotRangePart = slotRange.split("-");
for (int slot = Integer.valueOf(slotRangePart[0]); slot <= Integer
.valueOf(slotRangePart[1]); slot++) {
info.addAvailableSlot(slot);
}
} else {
// single slot
info.addAvailableSlot(Integer.valueOf(slotRange));
}
}
}

View File

@@ -8,28 +8,28 @@ public interface Hashing {
public ThreadLocal<MessageDigest> md5Holder = new ThreadLocal<MessageDigest>(); public ThreadLocal<MessageDigest> md5Holder = new ThreadLocal<MessageDigest>();
public static final Hashing MD5 = new Hashing() { public static final Hashing MD5 = new Hashing() {
public long hash(String key) { public long hash(String key) {
return hash(SafeEncoder.encode(key)); return hash(SafeEncoder.encode(key));
} }
public long hash(byte[] key) { public long hash(byte[] key) {
try { try {
if (md5Holder.get() == null) { if (md5Holder.get() == null) {
md5Holder.set(MessageDigest.getInstance("MD5")); md5Holder.set(MessageDigest.getInstance("MD5"));
} }
} catch (NoSuchAlgorithmException e) { } catch (NoSuchAlgorithmException e) {
throw new IllegalStateException("++++ no md5 algorythm found"); throw new IllegalStateException("++++ no md5 algorythm found");
} }
MessageDigest md5 = md5Holder.get(); MessageDigest md5 = md5Holder.get();
md5.reset(); md5.reset();
md5.update(key); md5.update(key);
byte[] bKey = md5.digest(); byte[] bKey = md5.digest();
long res = ((long) (bKey[3] & 0xFF) << 24) long res = ((long) (bKey[3] & 0xFF) << 24)
| ((long) (bKey[2] & 0xFF) << 16) | ((long) (bKey[2] & 0xFF) << 16)
| ((long) (bKey[1] & 0xFF) << 8) | (long) (bKey[0] & 0xFF); | ((long) (bKey[1] & 0xFF) << 8) | (long) (bKey[0] & 0xFF);
return res; return res;
} }
}; };
public long hash(String key); public long hash(String key);

View File

@@ -10,127 +10,127 @@ import java.util.Map;
import java.util.Set; import java.util.Set;
public class JedisByteHashMap implements Map<byte[], byte[]>, Cloneable, public class JedisByteHashMap implements Map<byte[], byte[]>, Cloneable,
Serializable { Serializable {
private static final long serialVersionUID = -6971431362627219416L; private static final long serialVersionUID = -6971431362627219416L;
private Map<ByteArrayWrapper, byte[]> internalMap = new HashMap<ByteArrayWrapper, byte[]>(); private Map<ByteArrayWrapper, byte[]> internalMap = new HashMap<ByteArrayWrapper, byte[]>();
public void clear() { public void clear() {
internalMap.clear(); internalMap.clear();
} }
public boolean containsKey(Object key) { public boolean containsKey(Object key) {
if (key instanceof byte[]) if (key instanceof byte[])
return internalMap.containsKey(new ByteArrayWrapper((byte[]) key)); return internalMap.containsKey(new ByteArrayWrapper((byte[]) key));
return internalMap.containsKey(key); return internalMap.containsKey(key);
} }
public boolean containsValue(Object value) { public boolean containsValue(Object value) {
return internalMap.containsValue(value); return internalMap.containsValue(value);
} }
public Set<java.util.Map.Entry<byte[], byte[]>> entrySet() { public Set<java.util.Map.Entry<byte[], byte[]>> entrySet() {
Iterator<java.util.Map.Entry<ByteArrayWrapper, byte[]>> iterator = internalMap Iterator<java.util.Map.Entry<ByteArrayWrapper, byte[]>> iterator = internalMap
.entrySet().iterator(); .entrySet().iterator();
HashSet<Entry<byte[], byte[]>> hashSet = new HashSet<java.util.Map.Entry<byte[], byte[]>>(); HashSet<Entry<byte[], byte[]>> hashSet = new HashSet<java.util.Map.Entry<byte[], byte[]>>();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entry<ByteArrayWrapper, byte[]> entry = iterator.next(); Entry<ByteArrayWrapper, byte[]> entry = iterator.next();
hashSet.add(new JedisByteEntry(entry.getKey().data, entry hashSet.add(new JedisByteEntry(entry.getKey().data, entry
.getValue())); .getValue()));
} }
return hashSet; return hashSet;
} }
public byte[] get(Object key) { public byte[] get(Object key) {
if (key instanceof byte[]) if (key instanceof byte[])
return internalMap.get(new ByteArrayWrapper((byte[]) key)); return internalMap.get(new ByteArrayWrapper((byte[]) key));
return internalMap.get(key); return internalMap.get(key);
} }
public boolean isEmpty() { public boolean isEmpty() {
return internalMap.isEmpty(); return internalMap.isEmpty();
} }
public Set<byte[]> keySet() { public Set<byte[]> keySet() {
Set<byte[]> keySet = new HashSet<byte[]>(); Set<byte[]> keySet = new HashSet<byte[]>();
Iterator<ByteArrayWrapper> iterator = internalMap.keySet().iterator(); Iterator<ByteArrayWrapper> iterator = internalMap.keySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
keySet.add(iterator.next().data); keySet.add(iterator.next().data);
} }
return keySet; return keySet;
} }
public byte[] put(byte[] key, byte[] value) { public byte[] put(byte[] key, byte[] value) {
return internalMap.put(new ByteArrayWrapper(key), value); return internalMap.put(new ByteArrayWrapper(key), value);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public void putAll(Map<? extends byte[], ? extends byte[]> m) { public void putAll(Map<? extends byte[], ? extends byte[]> m) {
Iterator<?> iterator = m.entrySet().iterator(); Iterator<?> iterator = m.entrySet().iterator();
while (iterator.hasNext()) { while (iterator.hasNext()) {
Entry<? extends byte[], ? extends byte[]> next = (Entry<? extends byte[], ? extends byte[]>) iterator Entry<? extends byte[], ? extends byte[]> next = (Entry<? extends byte[], ? extends byte[]>) iterator
.next(); .next();
internalMap.put(new ByteArrayWrapper(next.getKey()), next internalMap.put(new ByteArrayWrapper(next.getKey()),
.getValue()); next.getValue());
} }
} }
public byte[] remove(Object key) { public byte[] remove(Object key) {
if (key instanceof byte[]) if (key instanceof byte[])
return internalMap.remove(new ByteArrayWrapper((byte[]) key)); return internalMap.remove(new ByteArrayWrapper((byte[]) key));
return internalMap.remove(key); return internalMap.remove(key);
} }
public int size() { public int size() {
return internalMap.size(); return internalMap.size();
} }
public Collection<byte[]> values() { public Collection<byte[]> values() {
return internalMap.values(); return internalMap.values();
} }
private static final class ByteArrayWrapper { private static final class ByteArrayWrapper {
private final byte[] data; private final byte[] data;
public ByteArrayWrapper(byte[] data) { public ByteArrayWrapper(byte[] data) {
if (data == null) { if (data == null) {
throw new NullPointerException(); throw new NullPointerException();
} }
this.data = data; this.data = data;
} }
public boolean equals(Object other) { public boolean equals(Object other) {
if (!(other instanceof ByteArrayWrapper)) { if (!(other instanceof ByteArrayWrapper)) {
return false; return false;
} }
return Arrays.equals(data, ((ByteArrayWrapper) other).data); return Arrays.equals(data, ((ByteArrayWrapper) other).data);
} }
public int hashCode() { public int hashCode() {
return Arrays.hashCode(data); return Arrays.hashCode(data);
} }
} }
private static final class JedisByteEntry implements Entry<byte[], byte[]> { private static final class JedisByteEntry implements Entry<byte[], byte[]> {
private byte[] value; private byte[] value;
private byte[] key; private byte[] key;
public JedisByteEntry(byte[] key, byte[] value) { public JedisByteEntry(byte[] key, byte[] value) {
this.key = key; this.key = key;
this.value = value; this.value = value;
} }
public byte[] getKey() { public byte[] getKey() {
return this.key; return this.key;
} }
public byte[] getValue() { public byte[] getValue() {
return this.value; return this.value;
} }
public byte[] setValue(byte[] value) { public byte[] setValue(byte[] value) {
this.value = value; this.value = value;
return value; return value;
} }
} }
} }

View File

@@ -1,21 +1,34 @@
package redis.clients.util; package redis.clients.util;
public class JedisClusterCRC16 { public class JedisClusterCRC16 {
public final static int polynomial = 0x1021; // Represents x^16+x^12+x^5+1 public final static int polynomial = 0x1021; // Represents x^16+x^12+x^5+1
static int crc;
public static int getSlot(String key) {
crc = 0x0000;
for (byte b : key.getBytes()) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7-i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
// If coefficient of bit and remainder polynomial = 1 xor crc with polynomial
if (c15 ^ bit) crc ^= polynomial;
}
}
return crc &= 0xffff % 16384; public static int getSlot(String key) {
int s = key.indexOf("{");
if (s > -1) {
int e = key.indexOf("}", s+1);
if (e > -1 && e != s+1) {
key = key.substring(s+1, e);
}
}
return getCRC16(key) % 16384;
}
private static int getCRC16(String key) {
int crc = 0x0000;
for (byte b : key.getBytes()) {
for (int i = 0; i < 8; i++) {
boolean bit = ((b >> (7 - i) & 1) == 1);
boolean c15 = ((crc >> 15 & 1) == 1);
crc <<= 1;
// If coefficient of bit and remainder polynomial = 1 xor crc
// with polynomial
if (c15 ^ bit)
crc ^= polynomial;
}
}
return crc &= 0xffff ;
} }
} }

View File

@@ -40,7 +40,7 @@ public class MurmurHash implements Hashing {
* @return The 32 bit hash of the bytes in question. * @return The 32 bit hash of the bytes in question.
*/ */
public static int hash(byte[] data, int seed) { public static int hash(byte[] data, int seed) {
return hash(ByteBuffer.wrap(data), seed); return hash(ByteBuffer.wrap(data), seed);
} }
/** /**
@@ -57,7 +57,7 @@ public class MurmurHash implements Hashing {
* @return The 32-bit hash of the data in question. * @return The 32-bit hash of the data in question.
*/ */
public static int hash(byte[] data, int offset, int length, int seed) { public static int hash(byte[] data, int offset, int length, int seed) {
return hash(ByteBuffer.wrap(data, offset, length), seed); return hash(ByteBuffer.wrap(data, offset, length), seed);
} }
/** /**
@@ -70,97 +70,97 @@ public class MurmurHash implements Hashing {
* @return The 32 bit murmur hash of the bytes in the buffer. * @return The 32 bit murmur hash of the bytes in the buffer.
*/ */
public static int hash(ByteBuffer buf, int seed) { public static int hash(ByteBuffer buf, int seed) {
// save byte order for later restoration // save byte order for later restoration
ByteOrder byteOrder = buf.order(); ByteOrder byteOrder = buf.order();
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
int m = 0x5bd1e995; int m = 0x5bd1e995;
int r = 24; int r = 24;
int h = seed ^ buf.remaining(); int h = seed ^ buf.remaining();
int k; int k;
while (buf.remaining() >= 4) { while (buf.remaining() >= 4) {
k = buf.getInt(); k = buf.getInt();
k *= m; k *= m;
k ^= k >>> r; k ^= k >>> r;
k *= m; k *= m;
h *= m; h *= m;
h ^= k; h ^= k;
} }
if (buf.remaining() > 0) { if (buf.remaining() > 0) {
ByteBuffer finish = ByteBuffer.allocate(4).order( ByteBuffer finish = ByteBuffer.allocate(4).order(
ByteOrder.LITTLE_ENDIAN); ByteOrder.LITTLE_ENDIAN);
// for big-endian version, use this first: // for big-endian version, use this first:
// finish.position(4-buf.remaining()); // finish.position(4-buf.remaining());
finish.put(buf).rewind(); finish.put(buf).rewind();
h ^= finish.getInt(); h ^= finish.getInt();
h *= m; h *= m;
} }
h ^= h >>> 13; h ^= h >>> 13;
h *= m; h *= m;
h ^= h >>> 15; h ^= h >>> 15;
buf.order(byteOrder); buf.order(byteOrder);
return h; return h;
} }
public static long hash64A(byte[] data, int seed) { public static long hash64A(byte[] data, int seed) {
return hash64A(ByteBuffer.wrap(data), seed); return hash64A(ByteBuffer.wrap(data), seed);
} }
public static long hash64A(byte[] data, int offset, int length, int seed) { public static long hash64A(byte[] data, int offset, int length, int seed) {
return hash64A(ByteBuffer.wrap(data, offset, length), seed); return hash64A(ByteBuffer.wrap(data, offset, length), seed);
} }
public static long hash64A(ByteBuffer buf, int seed) { public static long hash64A(ByteBuffer buf, int seed) {
ByteOrder byteOrder = buf.order(); ByteOrder byteOrder = buf.order();
buf.order(ByteOrder.LITTLE_ENDIAN); buf.order(ByteOrder.LITTLE_ENDIAN);
long m = 0xc6a4a7935bd1e995L; long m = 0xc6a4a7935bd1e995L;
int r = 47; int r = 47;
long h = seed ^ (buf.remaining() * m); long h = seed ^ (buf.remaining() * m);
long k; long k;
while (buf.remaining() >= 8) { while (buf.remaining() >= 8) {
k = buf.getLong(); k = buf.getLong();
k *= m; k *= m;
k ^= k >>> r; k ^= k >>> r;
k *= m; k *= m;
h ^= k; h ^= k;
h *= m; h *= m;
} }
if (buf.remaining() > 0) { if (buf.remaining() > 0) {
ByteBuffer finish = ByteBuffer.allocate(8).order( ByteBuffer finish = ByteBuffer.allocate(8).order(
ByteOrder.LITTLE_ENDIAN); ByteOrder.LITTLE_ENDIAN);
// for big-endian version, do this first: // for big-endian version, do this first:
// finish.position(8-buf.remaining()); // finish.position(8-buf.remaining());
finish.put(buf).rewind(); finish.put(buf).rewind();
h ^= finish.getLong(); h ^= finish.getLong();
h *= m; h *= m;
} }
h ^= h >>> r; h ^= h >>> r;
h *= m; h *= m;
h ^= h >>> r; h ^= h >>> r;
buf.order(byteOrder); buf.order(byteOrder);
return h; return h;
} }
public long hash(byte[] key) { public long hash(byte[] key) {
return hash64A(key, 0x1234ABCD); return hash64A(key, 0x1234ABCD);
} }
public long hash(String key) { public long hash(String key) {
return hash(SafeEncoder.encode(key)); return hash(SafeEncoder.encode(key));
} }
} }

View File

@@ -45,6 +45,9 @@ public abstract class Pool<T> {
} }
public void returnResourceObject(final T resource) { public void returnResourceObject(final T resource) {
if (resource == null) {
return;
}
try { try {
internalPool.returnObject(resource); internalPool.returnObject(resource);
} catch (Exception e) { } catch (Exception e) {
@@ -54,11 +57,15 @@ public abstract class Pool<T> {
} }
public void returnBrokenResource(final T resource) { public void returnBrokenResource(final T resource) {
returnBrokenResourceObject(resource); if (resource != null) {
returnBrokenResourceObject(resource);
}
} }
public void returnResource(final T resource) { public void returnResource(final T resource) {
returnResourceObject(resource); if (resource != null) {
returnResourceObject(resource);
}
} }
public void destroy() { public void destroy() {

View File

@@ -29,84 +29,84 @@ public class RedisInputStream extends FilterInputStream {
protected int count, limit; protected int count, limit;
public RedisInputStream(InputStream in, int size) { public RedisInputStream(InputStream in, int size) {
super(in); super(in);
if (size <= 0) { if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0"); throw new IllegalArgumentException("Buffer size <= 0");
} }
buf = new byte[size]; buf = new byte[size];
} }
public RedisInputStream(InputStream in) { public RedisInputStream(InputStream in) {
this(in, 8192); this(in, 8192);
} }
public byte readByte() throws IOException { public byte readByte() throws IOException {
if (count == limit) { if (count == limit) {
fill(); fill();
} }
return buf[count++]; return buf[count++];
} }
public String readLine() { public String readLine() {
int b; int b;
byte c; byte c;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
try { try {
while (true) { while (true) {
if (count == limit) { if (count == limit) {
fill(); fill();
} }
if (limit == -1) if (limit == -1)
break; break;
b = buf[count++]; b = buf[count++];
if (b == '\r') { if (b == '\r') {
if (count == limit) { if (count == limit) {
fill(); fill();
} }
if (limit == -1) { if (limit == -1) {
sb.append((char) b); sb.append((char) b);
break; break;
} }
c = buf[count++]; c = buf[count++];
if (c == '\n') { if (c == '\n') {
break; break;
} }
sb.append((char) b); sb.append((char) b);
sb.append((char) c); sb.append((char) c);
} else { } else {
sb.append((char) b); sb.append((char) b);
} }
} }
} catch (IOException e) { } catch (IOException e) {
throw new JedisConnectionException(e); throw new JedisConnectionException(e);
} }
String reply = sb.toString(); String reply = sb.toString();
if (reply.length() == 0) { if (reply.length() == 0) {
throw new JedisConnectionException( throw new JedisConnectionException(
"It seems like server has closed the connection."); "It seems like server has closed the connection.");
} }
return reply; return reply;
} }
public int read(byte[] b, int off, int len) throws IOException { public int read(byte[] b, int off, int len) throws IOException {
if (count == limit) { if (count == limit) {
fill(); fill();
if (limit == -1) if (limit == -1)
return -1; return -1;
} }
final int length = Math.min(limit - count, len); final int length = Math.min(limit - count, len);
System.arraycopy(buf, count, b, off, length); System.arraycopy(buf, count, b, off, length);
count += length; count += length;
return length; return length;
} }
private void fill() throws IOException { private void fill() throws IOException {
limit = in.read(buf); limit = in.read(buf);
count = 0; count = 0;
} }
} }

View File

@@ -1,11 +1,13 @@
package redis.clients.util; package redis.clients.util;
import java.io.*; import java.io.FilterOutputStream;
import java.io.IOException;
import java.io.OutputStream;
/** /**
* The class implements a buffered output stream without synchronization * The class implements a buffered output stream without synchronization There
* There are also special operations like in-place string encoding. * are also special operations like in-place string encoding. This stream fully
* This stream fully ignore mark/reset and should not be used outside Jedis * ignore mark/reset and should not be used outside Jedis
*/ */
public final class RedisOutputStream extends FilterOutputStream { public final class RedisOutputStream extends FilterOutputStream {
protected final byte buf[]; protected final byte buf[];
@@ -13,218 +15,212 @@ public final class RedisOutputStream extends FilterOutputStream {
protected int count; protected int count;
public RedisOutputStream(final OutputStream out) { public RedisOutputStream(final OutputStream out) {
this(out, 8192); this(out, 8192);
} }
public RedisOutputStream(final OutputStream out, final int size) { public RedisOutputStream(final OutputStream out, final int size) {
super(out); super(out);
if (size <= 0) { if (size <= 0) {
throw new IllegalArgumentException("Buffer size <= 0"); throw new IllegalArgumentException("Buffer size <= 0");
} }
buf = new byte[size]; buf = new byte[size];
} }
private void flushBuffer() throws IOException { private void flushBuffer() throws IOException {
if (count > 0) { if (count > 0) {
out.write(buf, 0, count); out.write(buf, 0, count);
count = 0; count = 0;
} }
} }
public void write(final byte b) throws IOException { public void write(final byte b) throws IOException {
buf[count++] = b; if (count == buf.length) {
if (count == buf.length) { flushBuffer();
flushBuffer(); }
} buf[count++] = b;
} }
public void write(final byte[] b) throws IOException { public void write(final byte[] b) throws IOException {
write(b, 0, b.length); write(b, 0, b.length);
} }
public void write(final byte b[], final int off, final int len) throws IOException { public void write(final byte b[], final int off, final int len)
if (len >= buf.length) { throws IOException {
flushBuffer(); if (len >= buf.length) {
out.write(b, off, len); flushBuffer();
} else { out.write(b, off, len);
if (len >= buf.length - count) { } else {
flushBuffer(); if (len >= buf.length - count) {
} flushBuffer();
}
System.arraycopy(b, off, buf, count, len); System.arraycopy(b, off, buf, count, len);
count += len; count += len;
} }
} }
public void writeAsciiCrLf(final String in) throws IOException { public void writeAsciiCrLf(final String in) throws IOException {
final int size = in.length(); final int size = in.length();
for (int i = 0; i != size; ++i) { for (int i = 0; i != size; ++i) {
buf[count++] = (byte) in.charAt(i); if (count == buf.length) {
if (count == buf.length) { flushBuffer();
flushBuffer(); }
} buf[count++] = (byte) in.charAt(i);
} }
writeCrLf(); writeCrLf();
} }
public static boolean isSurrogate(final char ch) { public static boolean isSurrogate(final char ch) {
return ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE; return ch >= Character.MIN_SURROGATE && ch <= Character.MAX_SURROGATE;
} }
public static int utf8Length (final String str) { public static int utf8Length(final String str) {
int strLen = str.length(), utfLen = 0; int strLen = str.length(), utfLen = 0;
for(int i = 0; i != strLen; ++i) { for (int i = 0; i != strLen; ++i) {
char c = str.charAt(i); char c = str.charAt(i);
if (c < 0x80) { if (c < 0x80) {
utfLen++; utfLen++;
} else if (c < 0x800) { } else if (c < 0x800) {
utfLen += 2; utfLen += 2;
} else if (isSurrogate(c)) { } else if (isSurrogate(c)) {
i++; i++;
utfLen += 4; utfLen += 4;
} else { } else {
utfLen += 3; utfLen += 3;
} }
} }
return utfLen; return utfLen;
} }
public void writeCrLf() throws IOException { public void writeCrLf() throws IOException {
if (2 >= buf.length - count) { if (2 >= buf.length - count) {
flushBuffer(); flushBuffer();
} }
buf[count++] = '\r'; buf[count++] = '\r';
buf[count++] = '\n'; buf[count++] = '\n';
} }
public void writeUtf8CrLf(final String str) throws IOException { public void writeUtf8CrLf(final String str) throws IOException {
int strLen = str.length(); int strLen = str.length();
int i; int i;
for (i = 0; i < strLen; i++) { for (i = 0; i < strLen; i++) {
char c = str.charAt(i); char c = str.charAt(i);
if (!(c < 0x80)) break; if (!(c < 0x80))
buf[count++] = (byte) c; break;
if(count == buf.length) { if (count == buf.length) {
flushBuffer(); flushBuffer();
} }
} buf[count++] = (byte) c;
}
for (; i < strLen; i++) { for (; i < strLen; i++) {
char c = str.charAt(i); char c = str.charAt(i);
if (c < 0x80) { if (c < 0x80) {
buf[count++] = (byte) c; if (count == buf.length) {
if(count == buf.length) { flushBuffer();
flushBuffer(); }
} buf[count++] = (byte) c;
} else if (c < 0x800) { } else if (c < 0x800) {
if(2 >= buf.length - count) { if (2 >= buf.length - count) {
flushBuffer(); flushBuffer();
} }
buf[count++] = (byte)(0xc0 | (c >> 6)); buf[count++] = (byte) (0xc0 | (c >> 6));
buf[count++] = (byte)(0x80 | (c & 0x3f)); buf[count++] = (byte) (0x80 | (c & 0x3f));
} else if (isSurrogate(c)) { } else if (isSurrogate(c)) {
if(4 >= buf.length - count) { if (4 >= buf.length - count) {
flushBuffer(); flushBuffer();
} }
int uc = Character.toCodePoint(c, str.charAt(i++)); int uc = Character.toCodePoint(c, str.charAt(i++));
buf[count++] = ((byte)(0xf0 | ((uc >> 18)))); buf[count++] = ((byte) (0xf0 | ((uc >> 18))));
buf[count++] = ((byte)(0x80 | ((uc >> 12) & 0x3f))); buf[count++] = ((byte) (0x80 | ((uc >> 12) & 0x3f)));
buf[count++] = ((byte)(0x80 | ((uc >> 6) & 0x3f))); buf[count++] = ((byte) (0x80 | ((uc >> 6) & 0x3f)));
buf[count++] = ((byte)(0x80 | (uc & 0x3f))); buf[count++] = ((byte) (0x80 | (uc & 0x3f)));
} else { } else {
if(3 >= buf.length - count) { if (3 >= buf.length - count) {
flushBuffer(); flushBuffer();
} }
buf[count++] =((byte)(0xe0 | ((c >> 12)))); buf[count++] = ((byte) (0xe0 | ((c >> 12))));
buf[count++] =((byte)(0x80 | ((c >> 6) & 0x3f))); buf[count++] = ((byte) (0x80 | ((c >> 6) & 0x3f)));
buf[count++] =((byte)(0x80 | (c & 0x3f))); buf[count++] = ((byte) (0x80 | (c & 0x3f)));
} }
} }
writeCrLf(); writeCrLf();
} }
private final static int[] sizeTable = {9, 99, 999, 9999, 99999, 999999, 9999999, 99999999, 999999999, Integer.MAX_VALUE}; private final static int[] sizeTable = { 9, 99, 999, 9999, 99999, 999999,
9999999, 99999999, 999999999, Integer.MAX_VALUE };
private final static byte[] DigitTens = { private final static byte[] DigitTens = { '0', '0', '0', '0', '0', '0',
'0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '0', '1', '1', '1', '1', '1', '1', '1', '1', '1',
'1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '1', '2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3',
'2', '2', '2', '2', '2', '2', '2', '2', '2', '2', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4',
'3', '3', '3', '3', '3', '3', '3', '3', '3', '3', '4', '4', '4', '4', '4', '5', '5', '5', '5', '5', '5', '5', '5',
'4', '4', '4', '4', '4', '4', '4', '4', '4', '4', '5', '5', '6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '7',
'5', '5', '5', '5', '5', '5', '5', '5', '5', '5', '7', '7', '7', '7', '7', '7', '7', '7', '7', '8', '8', '8', '8',
'6', '6', '6', '6', '6', '6', '6', '6', '6', '6', '8', '8', '8', '8', '8', '8', '9', '9', '9', '9', '9', '9', '9',
'7', '7', '7', '7', '7', '7', '7', '7', '7', '7', '9', '9', '9', };
'8', '8', '8', '8', '8', '8', '8', '8', '8', '8',
'9', '9', '9', '9', '9', '9', '9', '9', '9', '9',
};
private final static byte[] DigitOnes = { private final static byte[] DigitOnes = { '0', '1', '2', '3', '4', '5',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '8', '9', '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '4', '5', '6', '7', '8', '9', '0', '1', '2', '3', '4', '5', '6',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', '7', '8', '9', };
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9',
};
private final static byte[] digits = { private final static byte[] digits = { '0', '1', '2', '3', '4', '5', '6',
'0', '1', '2', '3', '4', '5', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j',
'6', '7', '8', '9', 'a', 'b', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v', 'w',
'c', 'd', 'e', 'f', 'g', 'h', 'x', 'y', 'z' };
'i', 'j', 'k', 'l', 'm', 'n',
'o', 'p', 'q', 'r', 's', 't',
'u', 'v', 'w', 'x', 'y', 'z'
};
public void writeIntCrLf(int value) throws IOException { public void writeIntCrLf(int value) throws IOException {
if (value < 0) { if (value < 0) {
write('-'); write((byte) '-');
value = -value; value = -value;
} }
int size = 0; int size = 0;
while (value > sizeTable[size]) while (value > sizeTable[size])
size++; size++;
size++; size++;
if (size >= buf.length - count) { if (size >= buf.length - count) {
flushBuffer(); flushBuffer();
} }
int q, r; int q, r;
int charPos = count + size; int charPos = count + size;
while (value >= 65536) { while (value >= 65536) {
q = value / 100; q = value / 100;
r = value - ((q << 6) + (q << 5) + (q << 2)); r = value - ((q << 6) + (q << 5) + (q << 2));
value = q; value = q;
buf[--charPos] = DigitOnes[r]; buf[--charPos] = DigitOnes[r];
buf[--charPos] = DigitTens[r]; buf[--charPos] = DigitTens[r];
} }
for (; ;) { for (;;) {
q = (value * 52429) >>> (16 + 3); q = (value * 52429) >>> (16 + 3);
r = value - ((q << 3) + (q << 1)); r = value - ((q << 3) + (q << 1));
buf[--charPos] = digits[r]; buf[--charPos] = digits[r];
value = q; value = q;
if (value == 0) break; if (value == 0)
} break;
count += size; }
count += size;
writeCrLf(); writeCrLf();
} }
public void flush() throws IOException { public void flush() throws IOException {
flushBuffer(); flushBuffer();
out.flush(); out.flush();
} }
} }

View File

@@ -11,31 +11,31 @@ import redis.clients.jedis.exceptions.JedisException;
* *
*/ */
public class SafeEncoder { public class SafeEncoder {
public static byte[][] encodeMany(final String... strs){ public static byte[][] encodeMany(final String... strs) {
byte[][] many = new byte[strs.length][]; byte[][] many = new byte[strs.length][];
for(int i=0;i<strs.length;i++){ for (int i = 0; i < strs.length; i++) {
many[i] = encode(strs[i]); many[i] = encode(strs[i]);
}
return many;
} }
return many;
}
public static byte[] encode(final String str) { public static byte[] encode(final String str) {
try { try {
if (str == null) { if (str == null) {
throw new JedisDataException( throw new JedisDataException(
"value sent to redis cannot be null"); "value sent to redis cannot be null");
} }
return str.getBytes(Protocol.CHARSET); return str.getBytes(Protocol.CHARSET);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new JedisException(e); throw new JedisException(e);
} }
} }
public static String encode(final byte[] data) { public static String encode(final byte[] data) {
try { try {
return new String(data, Protocol.CHARSET); return new String(data, Protocol.CHARSET);
} catch (UnsupportedEncodingException e) { } catch (UnsupportedEncodingException e) {
throw new JedisException(e); throw new JedisException(e);
} }
} }
} }

View File

@@ -7,11 +7,11 @@ public abstract class ShardInfo<T> {
} }
public ShardInfo(int weight) { public ShardInfo(int weight) {
this.weight = weight; this.weight = weight;
} }
public int getWeight() { public int getWeight() {
return this.weight; return this.weight;
} }
protected abstract T createResource(); protected abstract T createResource();

View File

@@ -26,65 +26,68 @@ public class Sharded<R, S extends ShardInfo<R>> {
private Pattern tagPattern = null; private Pattern tagPattern = null;
// the tag is anything between {} // the tag is anything between {}
public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern
.compile("\\{(.+?)\\}"); .compile("\\{(.+?)\\}");
public Sharded(List<S> shards) { public Sharded(List<S> shards) {
this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works
// with 64-bits not 128 // with 64-bits not 128
} }
public Sharded(List<S> shards, Hashing algo) { public Sharded(List<S> shards, Hashing algo) {
this.algo = algo; this.algo = algo;
initialize(shards); initialize(shards);
} }
public Sharded(List<S> shards, Pattern tagPattern) { public Sharded(List<S> shards, Pattern tagPattern) {
this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good
// as we works with // as we works with
// 64-bits not 128 // 64-bits not 128
} }
public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) { public Sharded(List<S> shards, Hashing algo, Pattern tagPattern) {
this.algo = algo; this.algo = algo;
this.tagPattern = tagPattern; this.tagPattern = tagPattern;
initialize(shards); initialize(shards);
} }
private void initialize(List<S> shards) { private void initialize(List<S> shards) {
nodes = new TreeMap<Long, S>(); nodes = new TreeMap<Long, S>();
for (int i = 0; i != shards.size(); ++i) { for (int i = 0; i != shards.size(); ++i) {
final S shardInfo = shards.get(i); final S shardInfo = shards.get(i);
if (shardInfo.getName() == null) if (shardInfo.getName() == null)
for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo); nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n),
} shardInfo);
else }
for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { else
nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo); for (int n = 0; n < 160 * shardInfo.getWeight(); n++) {
} nodes.put(
resources.put(shardInfo, shardInfo.createResource()); this.algo.hash(shardInfo.getName() + "*"
} + shardInfo.getWeight() + n), shardInfo);
}
resources.put(shardInfo, shardInfo.createResource());
}
} }
public R getShard(byte[] key) { public R getShard(byte[] key) {
return resources.get(getShardInfo(key)); return resources.get(getShardInfo(key));
} }
public R getShard(String key) { public R getShard(String key) {
return resources.get(getShardInfo(key)); return resources.get(getShardInfo(key));
} }
public S getShardInfo(byte[] key) { public S getShardInfo(byte[] key) {
SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key)); SortedMap<Long, S> tail = nodes.tailMap(algo.hash(key));
if (tail.isEmpty()) { if (tail.isEmpty()) {
return nodes.get(nodes.firstKey()); return nodes.get(nodes.firstKey());
} }
return tail.get(tail.firstKey()); return tail.get(tail.firstKey());
} }
public S getShardInfo(String key) { public S getShardInfo(String key) {
return getShardInfo(SafeEncoder.encode(getKeyTag(key))); return getShardInfo(SafeEncoder.encode(getKeyTag(key)));
} }
/** /**
@@ -97,20 +100,19 @@ public class Sharded<R, S extends ShardInfo<R>> {
* @return The tag if it exists, or the original key * @return The tag if it exists, or the original key
*/ */
public String getKeyTag(String key) { public String getKeyTag(String key) {
if (tagPattern != null) { if (tagPattern != null) {
Matcher m = tagPattern.matcher(key); Matcher m = tagPattern.matcher(key);
if (m.find()) if (m.find())
return m.group(1); return m.group(1);
} }
return key; return key;
} }
public Collection<S> getAllShardInfo() { public Collection<S> getAllShardInfo() {
return Collections.unmodifiableCollection(nodes.values()); return Collections.unmodifiableCollection(nodes.values());
} }
public Collection<R> getAllShards() { public Collection<R> getAllShards() {
return Collections.unmodifiableCollection(resources.values()); return Collections.unmodifiableCollection(resources.values());
} }
} }

View File

@@ -4,50 +4,50 @@ import java.util.ArrayList;
import java.util.List; import java.util.List;
public class Slowlog { public class Slowlog {
private final long id; private final long id;
private final long timeStamp; private final long timeStamp;
private final long executionTime; private final long executionTime;
private final List<String> args; private final List<String> args;
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
public static List<Slowlog> from(List<Object> nestedMultiBulkReply){ public static List<Slowlog> from(List<Object> nestedMultiBulkReply) {
List<Slowlog> logs = new ArrayList<Slowlog>(nestedMultiBulkReply.size()); List<Slowlog> logs = new ArrayList<Slowlog>(nestedMultiBulkReply.size());
for(Object obj : nestedMultiBulkReply){ for (Object obj : nestedMultiBulkReply) {
List<Object> properties = (List<Object>)obj; List<Object> properties = (List<Object>) obj;
logs.add(new Slowlog(properties)); logs.add(new Slowlog(properties));
}
return logs;
} }
@SuppressWarnings("unchecked") return logs;
private Slowlog(List<Object> properties) { }
super();
this.id = (Long)properties.get(0);
this.timeStamp = (Long)properties.get(1);
this.executionTime = (Long)properties.get(2);
List<byte[]> bargs = (List<byte[]>)properties.get(3); @SuppressWarnings("unchecked")
this.args = new ArrayList<String>(bargs.size()); private Slowlog(List<Object> properties) {
super();
this.id = (Long) properties.get(0);
this.timeStamp = (Long) properties.get(1);
this.executionTime = (Long) properties.get(2);
for(byte[] barg:bargs){ List<byte[]> bargs = (List<byte[]>) properties.get(3);
this.args.add(SafeEncoder.encode(barg)); this.args = new ArrayList<String>(bargs.size());
}
for (byte[] barg : bargs) {
this.args.add(SafeEncoder.encode(barg));
} }
}
public long getId() { public long getId() {
return id; return id;
} }
public long getTimeStamp() { public long getTimeStamp() {
return timeStamp; return timeStamp;
} }
public long getExecutionTime() { public long getExecutionTime() {
return executionTime; return executionTime;
} }
public List<String> getArgs() { public List<String> getArgs() {
return args; return args;
} }
} }

View File

@@ -8,7 +8,7 @@ import redis.clients.jedis.BuilderFactory;
public class BuilderFactoryTest extends Assert { public class BuilderFactoryTest extends Assert {
@Test @Test
public void buildDouble() { public void buildDouble() {
Double build = BuilderFactory.DOUBLE.build("1.0".getBytes()); Double build = BuilderFactory.DOUBLE.build("1.0".getBytes());
assertEquals(new Double(1.0), build); assertEquals(new Double(1.0), build);
} }
} }

View File

@@ -13,32 +13,39 @@ public class ConnectionTest extends Assert {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
client = new Connection(); client = new Connection();
} }
@After @After
public void tearDown() throws Exception { public void tearDown() throws Exception {
client.disconnect(); client.disconnect();
} }
@Test(expected = JedisConnectionException.class) @Test(expected = JedisConnectionException.class)
public void checkUnkownHost() { public void checkUnkownHost() {
client.setHost("someunknownhost"); client.setHost("someunknownhost");
client.connect(); client.connect();
} }
@Test(expected = JedisConnectionException.class) @Test(expected = JedisConnectionException.class)
public void checkWrongPort() { public void checkWrongPort() {
client.setHost("localhost"); client.setHost("localhost");
client.setPort(55665); client.setPort(55665);
client.connect(); client.connect();
} }
@Test @Test
public void connectIfNotConnectedWhenSettingTimeoutInfinite() { public void connectIfNotConnectedWhenSettingTimeoutInfinite() {
client.setHost("localhost"); client.setHost("localhost");
client.setPort(6379); client.setPort(6379);
client.setTimeoutInfinite(); client.setTimeoutInfinite();
} }
@Test
public void checkCloseable() {
client.setHost("localhost");
client.setPort(6379);
client.connect();
client.close();
}
} }

View File

@@ -9,22 +9,22 @@ public class FragmentedByteArrayInputStream extends ByteArrayInputStream {
private int readMethodCallCount = 0; private int readMethodCallCount = 0;
public FragmentedByteArrayInputStream(final byte[] buf) { public FragmentedByteArrayInputStream(final byte[] buf) {
super(buf); super(buf);
} }
public synchronized int read(final byte[] b, final int off, final int len) { public synchronized int read(final byte[] b, final int off, final int len) {
readMethodCallCount++; readMethodCallCount++;
if (len <= 10) { if (len <= 10) {
// if the len <= 10, return as usual .. // if the len <= 10, return as usual ..
return super.read(b, off, len); return super.read(b, off, len);
} else { } else {
// else return the first half .. // else return the first half ..
return super.read(b, off, len / 2); return super.read(b, off, len / 2);
} }
} }
public int getReadMethodCallCount() { public int getReadMethodCallCount() {
return readMethodCallCount; return readMethodCallCount;
} }
} }

View File

@@ -12,46 +12,25 @@ public class HostAndPortUtil {
private static List<HostAndPort> clusterHostAndPortList = new ArrayList<HostAndPort>(); private static List<HostAndPort> clusterHostAndPortList = new ArrayList<HostAndPort>();
static { static {
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 1));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 2));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 3));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 4));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 5));
redisHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_PORT + 6));
HostAndPort defaulthnp1 = new HostAndPort("localhost", sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT));
Protocol.DEFAULT_PORT); sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 1));
redisHostAndPortList.add(defaulthnp1); sentinelHostAndPortList.add(new HostAndPort("localhost", Protocol.DEFAULT_SENTINEL_PORT + 2));
HostAndPort defaulthnp2 = new HostAndPort("localhost",
Protocol.DEFAULT_PORT + 1);
redisHostAndPortList.add(defaulthnp2);
HostAndPort defaulthnp3 = new HostAndPort("localhost",
Protocol.DEFAULT_PORT + 2);
redisHostAndPortList.add(defaulthnp3);
HostAndPort defaulthnp4 = new HostAndPort("localhost",
Protocol.DEFAULT_PORT + 3);
redisHostAndPortList.add(defaulthnp4);
HostAndPort defaulthnp5 = new HostAndPort("localhost",
Protocol.DEFAULT_PORT + 4);
redisHostAndPortList.add(defaulthnp5);
HostAndPort defaulthnp6 = new HostAndPort("localhost",
Protocol.DEFAULT_PORT + 5);
redisHostAndPortList.add(defaulthnp6);
HostAndPort defaulthnp7 = new HostAndPort("localhost",
Protocol.DEFAULT_SENTINEL_PORT);
sentinelHostAndPortList.add(defaulthnp7);
HostAndPort defaulthnp8 = new HostAndPort("localhost",
Protocol.DEFAULT_SENTINEL_PORT + 1);
sentinelHostAndPortList.add(defaulthnp8);
HostAndPort defaulthnp9 = new HostAndPort("localhost",
Protocol.DEFAULT_SENTINEL_PORT + 2);
sentinelHostAndPortList.add(defaulthnp9);
clusterHostAndPortList.add(new HostAndPort("localhost", 7379)); clusterHostAndPortList.add(new HostAndPort("localhost", 7379));
clusterHostAndPortList.add(new HostAndPort("localhost", 7380)); clusterHostAndPortList.add(new HostAndPort("localhost", 7380));
clusterHostAndPortList.add(new HostAndPort("localhost", 7381)); clusterHostAndPortList.add(new HostAndPort("localhost", 7381));
clusterHostAndPortList.add(new HostAndPort("localhost", 7382));
clusterHostAndPortList.add(new HostAndPort("localhost", 7383));
clusterHostAndPortList.add(new HostAndPort("localhost", 7384));
clusterHostAndPortList.add(new HostAndPort("localhost", 7385));
String envRedisHosts = System.getProperty("redis-hosts"); String envRedisHosts = System.getProperty("redis-hosts");
String envSentinelHosts = System.getProperty("sentinel-hosts"); String envSentinelHosts = System.getProperty("sentinel-hosts");

View File

@@ -0,0 +1,63 @@
package redis.clients.jedis.tests;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.util.ClusterNodeInformation;
import redis.clients.util.ClusterNodeInformationParser;
public class JedisClusterNodeInformationParserTest extends Assert {
private ClusterNodeInformationParser parser;
@Before
public void setUp() {
parser = new ClusterNodeInformationParser();
}
@Test
public void testParseNodeMyself() {
String nodeInfo = "9b0d2ab38ee31482c95fdb2c7847a0d40e88d518 :7379 myself,master - 0 0 1 connected 0-5460";
HostAndPort current = new HostAndPort("localhost", 7379);
ClusterNodeInformation clusterNodeInfo = parser
.parse(nodeInfo, current);
assertEquals(clusterNodeInfo.getNode(), current);
}
@Test
public void testParseNormalState() {
String nodeInfo = "5f4a2236d00008fba7ac0dd24b95762b446767bd 192.168.0.3:7380 master - 0 1400598804016 2 connected 5461-10922";
HostAndPort current = new HostAndPort("localhost", 7379);
ClusterNodeInformation clusterNodeInfo = parser
.parse(nodeInfo, current);
assertNotEquals(clusterNodeInfo.getNode(), current);
assertEquals(clusterNodeInfo.getNode(), new HostAndPort("192.168.0.3",
7380));
for (int slot = 5461; slot <= 10922; slot++) {
assertTrue(clusterNodeInfo.getAvailableSlots().contains(slot));
}
assertTrue(clusterNodeInfo.getSlotsBeingImported().isEmpty());
assertTrue(clusterNodeInfo.getSlotsBeingMigrated().isEmpty());
}
@Test
public void testParseSlotBeingMigrated() {
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);
assertEquals(clusterNodeInfo.getNode(), current);
for (int slot = 0; slot <= 5459; slot++) {
assertTrue(clusterNodeInfo.getAvailableSlots().contains(slot));
}
assertEquals(1, clusterNodeInfo.getSlotsBeingMigrated().size());
assertTrue(clusterNodeInfo.getSlotsBeingMigrated().contains(5460));
assertEquals(1, clusterNodeInfo.getSlotsBeingImported().size());
assertTrue(clusterNodeInfo.getSlotsBeingImported().contains(5461));
}
}

View File

@@ -0,0 +1,167 @@
package redis.clients.jedis.tests;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;
import java.util.Set;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.tests.utils.JedisClusterTestUtil;
public class JedisClusterReplicateTest {
private static Jedis node5;
private static Jedis node6;
private HostAndPort nodeInfo5 = HostAndPortUtil.getClusterServers().get(4);
private HostAndPort nodeInfo6 = HostAndPortUtil.getClusterServers().get(5);
private static int TIMEOUT = 15000; // cluster-node-timeout * 3
@Before
public void setUp() throws InterruptedException {
node5 = new Jedis(nodeInfo5.getHost(), nodeInfo5.getPort(), TIMEOUT);
node5.connect();
node5.flushAll();
node6 = new Jedis(nodeInfo6.getHost(), nodeInfo6.getPort(), TIMEOUT);
node6.connect();
// cannot flushall - it will be slave
// ---- configure cluster
// add nodes to cluster
node5.clusterMeet("127.0.0.1", nodeInfo6.getPort());
JedisClusterTestUtil.assertNodeIsKnown(node5, JedisClusterTestUtil.getNodeId(node6.clusterNodes()), 1000);
JedisClusterTestUtil.assertNodeIsKnown(node6, JedisClusterTestUtil.getNodeId(node5.clusterNodes()), 1000);
// split available slots across the three nodes
int[] node5Slots = new int[JedisCluster.HASHSLOTS];
for (int i = 0 ; i < JedisCluster.HASHSLOTS; i++) {
node5Slots[i] = i;
}
node5.clusterAddSlots(node5Slots);
JedisClusterTestUtil.waitForClusterReady(node5);
// replicate full 1on1
node6.clusterReplicate(JedisClusterTestUtil.getNodeId(node5
.clusterNodes()));
Map<Jedis, Jedis> replMap = new HashMap<Jedis, Jedis>();
replMap.put(node5, node6);
waitForReplicateReady(replMap, TIMEOUT);
JedisClusterTestUtil.waitForClusterReady(node5, node6);
}
private void waitForReplicateReady(Map<Jedis, Jedis> replMap, int timeoutMs) {
int interval = 100;
for (int timeout = 0; timeout <= timeoutMs; timeout += interval) {
for (Entry<Jedis, Jedis> entry : replMap.entrySet()) {
Jedis master = entry.getKey();
Jedis slave = entry.getValue();
String masterNodeId = JedisClusterTestUtil.getNodeId(master
.clusterNodes());
String slaveNodeId = JedisClusterTestUtil.getNodeId(slave
.clusterNodes());
try {
List<String> slaves = master.clusterSlaves(masterNodeId);
if (slaves.size() > 0 && slaves.get(0).contains(slaveNodeId)) {
return;
}
} catch (JedisDataException e) {
if (!e.getMessage().startsWith("ERR The specified node is not a master"))
throw e;
// retry...
}
}
try {
Thread.sleep(interval);
} catch (InterruptedException e) {
}
}
throw new JedisException("there seems to replication error");
}
@After
public void tearDown() throws InterruptedException {
// clear all slots
int[] slotsToDelete = new int[JedisCluster.HASHSLOTS];
for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {
slotsToDelete[i] = i;
}
node5.clusterDelSlots(slotsToDelete);
}
@Test
public void testClusterReplicate() {
// we're already replicate 1on1
List<String> slaveInfos = node5.clusterSlaves(JedisClusterTestUtil
.getNodeId(node5.clusterNodes()));
assertEquals(1, slaveInfos.size());
assertTrue(slaveInfos.get(0).contains(
JedisClusterTestUtil.getNodeId(node6.clusterNodes())));
}
@Test
public void testClusterFailover() throws InterruptedException {
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort(nodeInfo5.getHost(), nodeInfo5.getPort()));
JedisCluster jc = new JedisCluster(jedisClusterNode);
jc.set("51", "foo");
// node5 is responsible of taking care of slot for key "51" (7186)
node6.clusterFailover();
try {
// wait for failover
Map<Jedis, Jedis> replMap = new HashMap<Jedis, Jedis>();
replMap.put(node6, node5);
waitForReplicateReady(replMap, TIMEOUT);
JedisClusterTestUtil.waitForClusterReady(node5, node6);
List<String> slaveInfos = node6.clusterSlaves(JedisClusterTestUtil
.getNodeId(node6.clusterNodes()));
assertEquals(1, slaveInfos.size());
assertTrue(slaveInfos.get(0).contains(
JedisClusterTestUtil.getNodeId(node5.clusterNodes())));
} finally {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
}
// rollback
node5.clusterFailover();
Map<Jedis, Jedis> replMap = new HashMap<Jedis, Jedis>();
replMap.put(node5, node6);
waitForReplicateReady(replMap, TIMEOUT);
JedisClusterTestUtil.waitForClusterReady(node5, node6);
}
}
}

View File

@@ -1,9 +1,12 @@
package redis.clients.jedis.tests; package redis.clients.jedis.tests;
import java.util.ArrayList;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Set; import java.util.Set;
import org.junit.After; import org.junit.After;
import org.junit.AfterClass;
import org.junit.Assert; import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
@@ -11,21 +14,24 @@ import org.junit.Test;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisCluster; import redis.clients.jedis.JedisCluster;
import redis.clients.jedis.Pipeline;
import redis.clients.jedis.exceptions.JedisAskDataException; import redis.clients.jedis.exceptions.JedisAskDataException;
import redis.clients.jedis.exceptions.JedisClusterException; import redis.clients.jedis.exceptions.JedisClusterException;
import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException; import redis.clients.jedis.exceptions.JedisClusterMaxRedirectionsException;
import redis.clients.jedis.exceptions.JedisException;
import redis.clients.jedis.exceptions.JedisMovedDataException; import redis.clients.jedis.exceptions.JedisMovedDataException;
import redis.clients.jedis.tests.utils.JedisClusterTestUtil;
import redis.clients.util.JedisClusterCRC16; import redis.clients.util.JedisClusterCRC16;
public class JedisClusterTest extends Assert { public class JedisClusterTest extends Assert {
private Jedis node1; private static Jedis node1;
private Jedis node2; private static Jedis node2;
private Jedis node3; private static Jedis node3;
private static Jedis node4;
private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0); private HostAndPort nodeInfo1 = HostAndPortUtil.getClusterServers().get(0);
private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1); private HostAndPort nodeInfo2 = HostAndPortUtil.getClusterServers().get(1);
private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2); private HostAndPort nodeInfo3 = HostAndPortUtil.getClusterServers().get(2);
private HostAndPort nodeInfo4 = HostAndPortUtil.getClusterServers().get(3);
@Before @Before
public void setUp() throws InterruptedException { public void setUp() throws InterruptedException {
@@ -41,44 +47,82 @@ public class JedisClusterTest extends Assert {
node3.connect(); node3.connect();
node3.flushAll(); node3.flushAll();
node4 = new Jedis(nodeInfo4.getHost(), nodeInfo4.getPort());
node4.connect();
node4.flushAll();
// ---- configure cluster // ---- configure cluster
// add nodes to cluster // add nodes to cluster
node1.clusterMeet("127.0.0.1", nodeInfo1.getPort());
node1.clusterMeet("127.0.0.1", nodeInfo2.getPort()); node1.clusterMeet("127.0.0.1", nodeInfo2.getPort());
node1.clusterMeet("127.0.0.1", nodeInfo3.getPort()); node1.clusterMeet("127.0.0.1", nodeInfo3.getPort());
// split available slots across the three nodes // split available slots across the three nodes
int slotsPerNode = JedisCluster.HASHSLOTS / 3; int slotsPerNode = JedisCluster.HASHSLOTS / 3;
Pipeline pipeline1 = node1.pipelined(); int[] node1Slots = new int[slotsPerNode];
Pipeline pipeline2 = node2.pipelined(); int[] node2Slots = new int[slotsPerNode+1];
Pipeline pipeline3 = node3.pipelined(); int[] node3Slots = new int[slotsPerNode];
for (int i = 0; i < JedisCluster.HASHSLOTS; i++) { for (int i = 0, slot1 = 0, slot2 = 0, slot3 = 0 ; i < JedisCluster.HASHSLOTS; i++) {
if (i < slotsPerNode) { if (i < slotsPerNode) {
pipeline1.clusterAddSlots(i); node1Slots[slot1++] = i;
} else if (i > slotsPerNode * 2) { } else if (i > slotsPerNode * 2) {
pipeline3.clusterAddSlots(i); node3Slots[slot3++] = i;
} else { } else {
pipeline2.clusterAddSlots(i); node2Slots[slot2++] = i;
} }
} }
pipeline1.sync();
pipeline2.sync();
pipeline3.sync();
waitForClusterReady(); node1.clusterAddSlots(node1Slots);
node2.clusterAddSlots(node2Slots);
node3.clusterAddSlots(node3Slots);
JedisClusterTestUtil.waitForClusterReady(node1, node2, node3);
}
@AfterClass
public static void cleanUp() {
int slotTest = JedisClusterCRC16.getSlot("test");
int slot51 = JedisClusterCRC16.getSlot("51");
String node1Id = JedisClusterTestUtil.getNodeId(node1.clusterNodes());
String node2Id = JedisClusterTestUtil.getNodeId(node2.clusterNodes());
String node3Id = JedisClusterTestUtil.getNodeId(node3.clusterNodes());
node2.clusterSetSlotNode(slotTest, node3Id);
node2.clusterSetSlotNode(slot51, node3Id);
node2.clusterDelSlots(slotTest, slot51);
// forget about all nodes
node1.clusterForget(node2Id);
node1.clusterForget(node3Id);
node2.clusterForget(node1Id);
node2.clusterForget(node3Id);
node3.clusterForget(node1Id);
node3.clusterForget(node2Id);
} }
@After @After
public void tearDown() { public void tearDown() throws InterruptedException {
// clear all slots // clear all slots
int[] slotsToDelete = new int[JedisCluster.HASHSLOTS]; int[] slotsToDelete = new int[JedisCluster.HASHSLOTS];
for (int i = 0; i < JedisCluster.HASHSLOTS; i++) { for (int i = 0; i < JedisCluster.HASHSLOTS; i++) {
slotsToDelete[i] = i; slotsToDelete[i] = i;
} }
node1.clusterDelSlots(slotsToDelete); node1.clusterDelSlots(slotsToDelete);
node2.clusterDelSlots(slotsToDelete); node2.clusterDelSlots(slotsToDelete);
node3.clusterDelSlots(slotsToDelete); node3.clusterDelSlots(slotsToDelete);
clearAnyInconsistentMigration(node1);
clearAnyInconsistentMigration(node2);
clearAnyInconsistentMigration(node3);
}
private void clearAnyInconsistentMigration(Jedis node) {
// FIXME: it's too slow... apply pipeline if possible
List<Integer> slots = getInconsistentSlots(node.clusterNodes());
for (Integer slot : slots) {
node.clusterSetSlotStable(slot);
}
} }
@Test(expected = JedisMovedDataException.class) @Test(expected = JedisMovedDataException.class)
@@ -102,7 +146,7 @@ public class JedisClusterTest extends Assert {
@Test(expected = JedisAskDataException.class) @Test(expected = JedisAskDataException.class)
public void testThrowAskException() { public void testThrowAskException() {
int keySlot = JedisClusterCRC16.getSlot("test"); int keySlot = JedisClusterCRC16.getSlot("test");
String node3Id = getNodeId(node3.clusterNodes()); String node3Id = JedisClusterTestUtil.getNodeId(node3.clusterNodes());
node2.clusterSetSlotMigrating(keySlot, node3Id); node2.clusterSetSlotMigrating(keySlot, node3Id);
node2.get("test"); node2.get("test");
} }
@@ -112,7 +156,7 @@ public class JedisClusterTest extends Assert {
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>(); Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379)); jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379));
JedisCluster jc = new JedisCluster(jedisClusterNode); JedisCluster jc = new JedisCluster(jedisClusterNode);
assertEquals(jc.getClusterNodes().size(), 3); assertEquals(3, jc.getClusterNodes().size());
} }
@Test @Test
@@ -136,7 +180,7 @@ public class JedisClusterTest extends Assert {
node3.clusterDelSlots(slot51); node3.clusterDelSlots(slot51);
node3.clusterAddSlots(slot51); node3.clusterAddSlots(slot51);
waitForClusterReady(); JedisClusterTestUtil.waitForClusterReady(node1, node2, node3);
jc.set("51", "foo"); jc.set("51", "foo");
assertEquals("foo", jc.get("51")); assertEquals("foo", jc.get("51"));
} }
@@ -147,8 +191,8 @@ public class JedisClusterTest extends Assert {
jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379)); jedisClusterNode.add(new HostAndPort("127.0.0.1", 7379));
JedisCluster jc = new JedisCluster(jedisClusterNode); JedisCluster jc = new JedisCluster(jedisClusterNode);
int slot51 = JedisClusterCRC16.getSlot("51"); int slot51 = JedisClusterCRC16.getSlot("51");
node3.clusterSetSlotImporting(slot51, getNodeId(node2.clusterNodes())); node3.clusterSetSlotImporting(slot51, JedisClusterTestUtil.getNodeId(node2.clusterNodes()));
node2.clusterSetSlotMigrating(slot51, getNodeId(node3.clusterNodes())); node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));
jc.set("51", "foo"); jc.set("51", "foo");
assertEquals("foo", jc.get("51")); assertEquals("foo", jc.get("51"));
} }
@@ -168,29 +212,193 @@ public class JedisClusterTest extends Assert {
JedisCluster jc = new JedisCluster(jedisClusterNode); JedisCluster jc = new JedisCluster(jedisClusterNode);
int slot51 = JedisClusterCRC16.getSlot("51"); int slot51 = JedisClusterCRC16.getSlot("51");
// This will cause an infinite redirection loop // This will cause an infinite redirection loop
node2.clusterSetSlotMigrating(slot51, getNodeId(node3.clusterNodes())); node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));
jc.set("51", "foo"); jc.set("51", "foo");
} }
private String getNodeId(String infoOutput) { @Test
for (String infoLine : infoOutput.split("\n")) { public void testRedisHashtag() {
if (infoLine.contains("myself")) { assertEquals(JedisClusterCRC16.getSlot("{bar"), JedisClusterCRC16.getSlot("foo{{bar}}zap"));
return infoLine.split(" ")[0]; assertEquals(JedisClusterCRC16.getSlot("{user1000}.following"), JedisClusterCRC16.getSlot("{user1000}.followers"));
} assertNotEquals(JedisClusterCRC16.getSlot("foo{}{bar}"), JedisClusterCRC16.getSlot("bar"));
} assertEquals(JedisClusterCRC16.getSlot("foo{bar}{zap}"), JedisClusterCRC16.getSlot("bar"));
return "";
} }
private void waitForClusterReady() throws InterruptedException { @Test
boolean clusterOk = false; public void testClusterForgetNode() throws InterruptedException {
while (!clusterOk) { // at first, join node4 to cluster
if (node1.clusterInfo().split("\n")[0].contains("ok") node1.clusterMeet("127.0.0.1", nodeInfo4.getPort());
&& node2.clusterInfo().split("\n")[0].contains("ok")
&& node3.clusterInfo().split("\n")[0].contains("ok")) { String node7Id = JedisClusterTestUtil.getNodeId(node4.clusterNodes());
clusterOk = true;
JedisClusterTestUtil.assertNodeIsKnown(node3, node7Id, 1000);
JedisClusterTestUtil.assertNodeIsKnown(node2, node7Id, 1000);
JedisClusterTestUtil.assertNodeIsKnown(node1, node7Id, 1000);
assertNodeHandshakeEnded(node3, 1000);
assertNodeHandshakeEnded(node2, 1000);
assertNodeHandshakeEnded(node1, 1000);
assertEquals(4, node1.clusterNodes().split("\n").length);
assertEquals(4, node2.clusterNodes().split("\n").length);
assertEquals(4, node3.clusterNodes().split("\n").length);
// do cluster forget
node1.clusterForget(node7Id);
node2.clusterForget(node7Id);
node3.clusterForget(node7Id);
JedisClusterTestUtil.assertNodeIsUnknown(node1, node7Id, 1000);
JedisClusterTestUtil.assertNodeIsUnknown(node2, node7Id, 1000);
JedisClusterTestUtil.assertNodeIsUnknown(node3, node7Id, 1000);
assertEquals(3, node1.clusterNodes().split("\n").length);
assertEquals(3, node2.clusterNodes().split("\n").length);
assertEquals(3, node3.clusterNodes().split("\n").length);
}
@Test
public void testClusterFlushSlots() {
String slotRange = getNodeServingSlotRange(node1.clusterNodes());
assertNotNull(slotRange);
try {
node1.clusterFlushSlots();
assertNull(getNodeServingSlotRange(node1.clusterNodes()));
} finally {
// rollback
String[] rangeInfo = slotRange.split("-");
int lower = Integer.parseInt(rangeInfo[0]);
int upper = Integer.parseInt(rangeInfo[1]);
int[] node1Slots = new int[upper - lower + 1];
for (int i = 0 ; lower <= upper ; ) {
node1Slots[i++] = lower++;
} }
Thread.sleep(50); node1.clusterAddSlots(node1Slots);
} }
} }
@Test
public void testClusterKeySlot() {
// It assumes JedisClusterCRC16 is correctly implemented
assertEquals(node1.clusterKeySlot("foo{bar}zap}").intValue(), JedisClusterCRC16.getSlot("foo{bar}zap"));
assertEquals(node1.clusterKeySlot("{user1000}.following").intValue(), JedisClusterCRC16.getSlot("{user1000}.following"));
}
@Test
public void testClusterCountKeysInSlot() {
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));
JedisCluster jc = new JedisCluster(jedisClusterNode);
for (int index = 0 ; index < 5 ; index++) {
jc.set("foo{bar}" + index, "hello");
}
int slot = JedisClusterCRC16.getSlot("foo{bar}");
assertEquals(5, node1.clusterCountKeysInSlot(slot).intValue());
}
@Test
public void testStableSlotWhenMigratingNodeOrImportingNodeIsNotSpecified() throws InterruptedException {
Set<HostAndPort> jedisClusterNode = new HashSet<HostAndPort>();
jedisClusterNode.add(new HostAndPort(nodeInfo1.getHost(), nodeInfo1.getPort()));
JedisCluster jc = new JedisCluster(jedisClusterNode);
int slot51 = JedisClusterCRC16.getSlot("51");
jc.set("51", "foo");
// node2 is responsible of taking care of slot51 (7186)
node3.clusterSetSlotImporting(slot51, JedisClusterTestUtil.getNodeId(node2.clusterNodes()));
assertEquals("foo", jc.get("51"));
node3.clusterSetSlotStable(slot51);
assertEquals("foo", jc.get("51"));
node2.clusterSetSlotMigrating(slot51, JedisClusterTestUtil.getNodeId(node3.clusterNodes()));
//assertEquals("foo", jc.get("51")); // it leads Max Redirections
node2.clusterSetSlotStable(slot51);
assertEquals("foo", jc.get("51"));
}
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")) {
if (infoLine.contains("myself")) {
try {
return infoLine.split(" ")[8];
} catch (ArrayIndexOutOfBoundsException e) {
return null;
}
}
}
return null;
}
private List<Integer> getInconsistentSlots(String infoOuput) {
for (String infoLine : infoOuput.split("\n")) {
if (infoLine.contains("myself")) {
return getSlotsBeingMigrated(infoLine);
}
}
return null;
}
private List<Integer> getSlotsBeingMigrated(String infoLine) {
List<Integer> inconsistentSlots = new ArrayList<Integer>();
String[] splitted = infoLine.split(" ");
if (splitted.length > 8) {
for (int index = 8 ; index < splitted.length ; index++) {
String info = splitted[index];
Integer slot = getSlotFromMigrationInfo(info);
if (slot != null) {
inconsistentSlots.add(slot);
}
}
}
return inconsistentSlots;
}
private Integer getSlotFromMigrationInfo(String info) {
if (info.startsWith("[")) {
if (info.contains("-<-")) {
return Integer.parseInt(info.split("-<-")[0].substring(1));
} else if (info.contains("->-")) {
return Integer.parseInt(info.split("->-")[0].substring(1));
}
}
return null;
}
private void assertNodeHandshakeEnded(Jedis node, int timeoutMs) {
int sleepInterval = 100;
for (int sleepTime = 0 ; sleepTime <= timeoutMs ; sleepTime += sleepInterval) {
boolean isHandshaking = isAnyNodeHandshaking(node);
if (!isHandshaking)
return;
try {
Thread.sleep(sleepInterval);
} catch (InterruptedException e) {
}
}
throw new JedisException("Node handshaking is not ended");
}
private boolean isAnyNodeHandshaking(Jedis node) {
String infoOutput = node.clusterNodes();
for (String infoLine : infoOutput.split("\n")) {
if (infoLine.contains("handshake")) {
return true;
}
}
return false;
}
} }

View File

@@ -11,6 +11,7 @@ import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPool; import redis.clients.jedis.JedisPool;
import redis.clients.jedis.JedisPoolConfig; import redis.clients.jedis.JedisPoolConfig;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisConnectionException;
public class JedisPoolTest extends Assert { public class JedisPoolTest extends Assert {
@@ -18,59 +19,59 @@ public class JedisPoolTest extends Assert {
@Test @Test
public void checkConnections() { public void checkConnections() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
hnp.getPort(), 2000); hnp.getPort(), 2000);
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.set("foo", "bar"); jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
pool.returnResource(jedis); pool.returnResource(jedis);
pool.destroy(); pool.destroy();
} }
@Test @Test
public void checkConnectionWithDefaultPort() { public void checkConnectionWithDefaultPort() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
hnp.getPort()); hnp.getPort());
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.set("foo", "bar"); jedis.set("foo", "bar");
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
pool.returnResource(jedis); pool.returnResource(jedis);
pool.destroy(); pool.destroy();
} }
@Test @Test
public void checkJedisIsReusedWhenReturned() { public void checkJedisIsReusedWhenReturned() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
hnp.getPort()); hnp.getPort());
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.set("foo", "0"); jedis.set("foo", "0");
pool.returnResource(jedis); pool.returnResource(jedis);
jedis = pool.getResource(); jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.incr("foo"); jedis.incr("foo");
pool.returnResource(jedis); pool.returnResource(jedis);
pool.destroy(); pool.destroy();
} }
@Test @Test
public void checkPoolRepairedWhenJedisIsBroken() { public void checkPoolRepairedWhenJedisIsBroken() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(), JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
hnp.getPort()); hnp.getPort());
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.quit(); jedis.quit();
pool.returnBrokenResource(jedis); pool.returnBrokenResource(jedis);
jedis = pool.getResource(); jedis = pool.getResource();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.incr("foo"); jedis.incr("foo");
pool.returnResource(jedis); pool.returnResource(jedis);
pool.destroy(); pool.destroy();
} }
@Test(expected = JedisConnectionException.class) @Test(expected = JedisConnectionException.class)
@@ -92,8 +93,8 @@ public class JedisPoolTest extends Assert {
public void securePool() { public void securePool() {
JedisPoolConfig config = new JedisPoolConfig(); JedisPoolConfig config = new JedisPoolConfig();
config.setTestOnBorrow(true); config.setTestOnBorrow(true);
JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(), 2000, JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(),
"foobared"); 2000, "foobared");
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
jedis.set("foo", "bar"); jedis.set("foo", "bar");
pool.returnResource(jedis); pool.returnResource(jedis);
@@ -176,4 +177,65 @@ public class JedisPoolTest extends Assert {
pool0.returnResource(jedis); pool0.returnResource(jedis);
pool0.destroy(); pool0.destroy();
} }
@Test
public void returnResourceShouldResetState() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(),
2000, "foobared");
Jedis jedis = pool.getResource();
try {
jedis.set("hello", "jedis");
Transaction t = jedis.multi();
t.set("hello", "world");
} finally {
jedis.close();
}
Jedis jedis2 = pool.getResource();
try {
assertTrue(jedis == jedis2);
assertEquals("jedis", jedis2.get("hello"));
} finally {
jedis2.close();
}
pool.destroy();
}
@Test
public void checkResourceIsCloseable() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisPool pool = new JedisPool(config, hnp.getHost(), hnp.getPort(),
2000, "foobared");
Jedis jedis = pool.getResource();
try {
jedis.set("hello", "jedis");
} finally {
jedis.close();
}
Jedis jedis2 = pool.getResource();
try {
assertEquals(jedis, jedis2);
} finally {
jedis2.close();
}
}
@Test
public void returnNullObjectShouldNotFail() {
JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.getHost(),
hnp.getPort(), 2000, "foobared", 0, "my_shiny_client_name");
pool.returnBrokenResource(null);
pool.returnResource(null);
pool.returnResourceObject(null);
}
} }

View File

@@ -2,17 +2,17 @@ package redis.clients.jedis.tests;
import java.util.HashSet; import java.util.HashSet;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicReference;
import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.apache.commons.pool2.impl.GenericObjectPoolConfig;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import redis.clients.jedis.DebugParams;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisPubSub;
import redis.clients.jedis.JedisSentinelPool; import redis.clients.jedis.JedisSentinelPool;
import redis.clients.jedis.Transaction;
import redis.clients.jedis.exceptions.JedisConnectionException;
import redis.clients.jedis.tests.utils.JedisSentinelTestUtil;
public class JedisSentinelPoolTest extends JedisTestBase { public class JedisSentinelPoolTest extends JedisTestBase {
private static final String MASTER_NAME = "mymaster"; private static final String MASTER_NAME = "mymaster";
@@ -21,12 +21,8 @@ public class JedisSentinelPoolTest extends JedisTestBase {
.get(2); .get(2);
protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers() protected static HostAndPort slave1 = HostAndPortUtil.getRedisServers()
.get(3); .get(3);
protected static HostAndPort slave2 = HostAndPortUtil.getRedisServers()
.get(4);
protected static HostAndPort sentinel1 = HostAndPortUtil protected static HostAndPort sentinel1 = HostAndPortUtil
.getSentinelServers().get(1); .getSentinelServers().get(1);
protected static HostAndPort sentinel2 = HostAndPortUtil
.getSentinelServers().get(2);
protected static Jedis sentinelJedis1; protected static Jedis sentinelJedis1;
@@ -35,7 +31,6 @@ public class JedisSentinelPoolTest extends JedisTestBase {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
sentinels.add(sentinel1.toString()); sentinels.add(sentinel1.toString());
sentinels.add(sentinel2.toString());
sentinelJedis1 = new Jedis(sentinel1.getHost(), sentinel1.getPort()); sentinelJedis1 = new Jedis(sentinel1.getHost(), sentinel1.getPort());
} }
@@ -45,17 +40,96 @@ public class JedisSentinelPoolTest extends JedisTestBase {
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels, JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
new GenericObjectPoolConfig(), 1000, "foobared", 2); new GenericObjectPoolConfig(), 1000, "foobared", 2);
// perform failover forceFailover(pool);
doSegFaultMaster(pool); forceFailover(pool);
// perform failover once again
doSegFaultMaster(pool);
// you can test failover as much as possible // you can test failover as much as possible
// but you need to prepare additional slave per failover
} }
private void doSegFaultMaster(JedisSentinelPool pool) @Test
public void returnResourceShouldResetState() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
config, 1000, "foobared", 2);
Jedis jedis = pool.getResource();
Jedis jedis2 = null;
try {
jedis.set("hello", "jedis");
Transaction t = jedis.multi();
t.set("hello", "world");
pool.returnResource(jedis);
jedis2 = pool.getResource();
assertTrue(jedis == jedis2);
assertEquals("jedis", jedis2.get("hello"));
} catch (JedisConnectionException e) {
if (jedis2 != null) {
pool.returnBrokenResource(jedis2);
jedis2 = null;
}
} finally {
if (jedis2 != null)
pool.returnResource(jedis2);
pool.destroy();
}
}
@Test
public void checkResourceIsCloseable() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
config, 1000, "foobared", 2);
Jedis jedis = pool.getResource();
try {
jedis.set("hello", "jedis");
} finally {
jedis.close();
}
Jedis jedis2 = pool.getResource();
try {
assertEquals(jedis, jedis2);
} finally {
jedis2.close();
}
}
@Test
public void returnResourceWithNullResource() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
config, 1000, "foobared", 2);
Jedis nullJedis = null;
pool.returnResource(nullJedis);
pool.destroy();
}
@Test
public void returnBrokenResourceWithNullResource() {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
JedisSentinelPool pool = new JedisSentinelPool(MASTER_NAME, sentinels,
config, 1000, "foobared", 2);
Jedis nullJedis = null;
pool.returnBrokenResource(nullJedis);
pool.destroy();
}
private void forceFailover(JedisSentinelPool pool)
throws InterruptedException { throws InterruptedException {
HostAndPort oldMaster = pool.getCurrentHostMaster(); HostAndPort oldMaster = pool.getCurrentHostMaster();
@@ -63,12 +137,14 @@ public class JedisSentinelPoolTest extends JedisTestBase {
Jedis jedis = pool.getResource(); Jedis jedis = pool.getResource();
assertEquals("PONG", jedis.ping()); assertEquals("PONG", jedis.ping());
try { // It can throw JedisDataException while there's no slave to promote
jedis.debug(DebugParams.SEGFAULT()); // There's nothing we can do, so we just pass Exception to make test
} catch (Exception e) { // fail fast
} sentinelJedis1.sentinelFailover(MASTER_NAME);
waitForFailover(pool, oldMaster); waitForFailover(pool, oldMaster);
// JedisSentinelPool recognize master but may not changed internal pool
// yet
Thread.sleep(100); Thread.sleep(100);
jedis = pool.getResource(); jedis = pool.getResource();
@@ -79,62 +155,15 @@ public class JedisSentinelPoolTest extends JedisTestBase {
private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster) private void waitForFailover(JedisSentinelPool pool, HostAndPort oldMaster)
throws InterruptedException { throws InterruptedException {
waitForJedisSentinelPoolRecognizeNewMaster(pool); HostAndPort newMaster = JedisSentinelTestUtil
.waitForNewPromotedMaster(sentinelJedis1);
waitForJedisSentinelPoolRecognizeNewMaster(pool, newMaster);
} }
private void waitForJedisSentinelPoolRecognizeNewMaster( private void waitForJedisSentinelPoolRecognizeNewMaster(
JedisSentinelPool pool) throws InterruptedException { JedisSentinelPool pool, HostAndPort newMaster)
throws InterruptedException {
final AtomicReference<String> newmaster = new AtomicReference<String>(
"");
sentinelJedis1.psubscribe(new JedisPubSub() {
@Override
public void onMessage(String channel, String message) {
// TODO Auto-generated method stub
}
@Override
public void onPMessage(String pattern, String channel,
String message) {
if (channel.equals("+switch-master")) {
newmaster.set(message);
punsubscribe();
}
// TODO Auto-generated method stub
}
@Override
public void onSubscribe(String channel, int subscribedChannels) {
// TODO Auto-generated method stub
}
@Override
public void onUnsubscribe(String channel, int subscribedChannels) {
// TODO Auto-generated method stub
}
@Override
public void onPUnsubscribe(String pattern, int subscribedChannels) {
// TODO Auto-generated method stub
}
@Override
public void onPSubscribe(String pattern, int subscribedChannels) {
// TODO Auto-generated method stub
}
}, "*");
String[] chunks = newmaster.get().split(" ");
HostAndPort newMaster = new HostAndPort(chunks[3],
Integer.parseInt(chunks[4]));
while (true) { while (true) {
String host = pool.getCurrentHostMaster().getHost(); String host = pool.getCurrentHostMaster().getHost();

View File

@@ -1,5 +1,6 @@
package redis.clients.jedis.tests; package redis.clients.jedis.tests;
import java.util.HashMap;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
@@ -9,24 +10,30 @@ import org.junit.Test;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.exceptions.JedisDataException;
import redis.clients.jedis.tests.utils.JedisSentinelTestUtil;
public class JedisSentinelTest extends JedisTestBase { public class JedisSentinelTest extends JedisTestBase {
private static final String MASTER_NAME = "mymaster"; private static final String MASTER_NAME = "mymaster";
private static final String MONITOR_MASTER_NAME = "mymastermonitor";
private static final String REMOVE_MASTER_NAME = "mymasterremove";
private static final String FAILOVER_MASTER_NAME = "mymasterfailover";
private static final String MASTER_IP = "127.0.0.1";
protected static HostAndPort master = HostAndPortUtil.getRedisServers() protected static HostAndPort master = HostAndPortUtil.getRedisServers()
.get(0); .get(0);
protected static HostAndPort slave = HostAndPortUtil.getRedisServers().get( protected static HostAndPort slave = HostAndPortUtil.getRedisServers()
5); .get(4);
protected static HostAndPort sentinel = HostAndPortUtil protected static HostAndPort sentinel = HostAndPortUtil
.getSentinelServers().get(0); .getSentinelServers().get(0);
protected static Jedis masterJedis; protected static HostAndPort sentinelForFailover = HostAndPortUtil
protected static Jedis slaveJedis; .getSentinelServers().get(2);
protected static Jedis sentinelJedis; protected static HostAndPort masterForFailover = HostAndPortUtil
.getRedisServers().get(5);
@Before @Before
public void setup() throws InterruptedException { public void setup() throws InterruptedException {
} }
@After @After
@@ -36,30 +43,166 @@ public class JedisSentinelTest extends JedisTestBase {
// to restore it (demote) // to restore it (demote)
// so, promote(slaveof) slave to master has no effect, not same to old // so, promote(slaveof) slave to master has no effect, not same to old
// Sentinel's behavior // Sentinel's behavior
ensureRemoved(MONITOR_MASTER_NAME);
ensureRemoved(REMOVE_MASTER_NAME);
} }
@Test @Test
public void sentinel() { public void sentinel() {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort()); Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
List<Map<String, String>> masters = j.sentinelMasters();
final String masterName = masters.get(0).get("name");
assertEquals(MASTER_NAME, masterName); try {
List<Map<String, String>> masters = j.sentinelMasters();
List<String> masterHostAndPort = j boolean inMasters = false;
.sentinelGetMasterAddrByName(masterName); for (Map<String, String> master : masters)
HostAndPort masterFromSentinel = new HostAndPort( if (MASTER_NAME.equals(master.get("name")))
masterHostAndPort.get(0), Integer.parseInt(masterHostAndPort inMasters = true;
.get(1)));
assertEquals(master, masterFromSentinel);
List<Map<String, String>> slaves = j.sentinelSlaves(masterName); assertTrue(inMasters);
assertTrue(slaves.size() > 0);
assertEquals(master.getPort(),
Integer.parseInt(slaves.get(0).get("master-port")));
// DO NOT RE-RUN TEST TOO FAST, RESET TAKES SOME TIME TO... RESET List<String> masterHostAndPort = j
assertEquals(Long.valueOf(1), j.sentinelReset(masterName)); .sentinelGetMasterAddrByName(MASTER_NAME);
assertEquals(Long.valueOf(0), j.sentinelReset("woof" + masterName)); HostAndPort masterFromSentinel = new HostAndPort(
masterHostAndPort.get(0),
Integer.parseInt(masterHostAndPort.get(1)));
assertEquals(master, masterFromSentinel);
List<Map<String, String>> slaves = j.sentinelSlaves(MASTER_NAME);
assertTrue(slaves.size() > 0);
assertEquals(master.getPort(),
Integer.parseInt(slaves.get(0).get("master-port")));
// DO NOT RE-RUN TEST TOO FAST, RESET TAKES SOME TIME TO... RESET
assertEquals(Long.valueOf(1), j.sentinelReset(MASTER_NAME));
assertEquals(Long.valueOf(0), j.sentinelReset("woof" + MASTER_NAME));
} finally {
j.close();
}
} }
@Test
public void sentinelFailover() throws InterruptedException {
Jedis j = 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);
masterHostAndPort = j
.sentinelGetMasterAddrByName(FAILOVER_MASTER_NAME);
HostAndPort newMaster = new HostAndPort(masterHostAndPort.get(0),
Integer.parseInt(masterHostAndPort.get(1)));
assertNotEquals(newMaster, currentMaster);
} finally {
j.close();
}
}
@Test
public void sentinelMonitor() {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
try {
// monitor new master
String result = j.sentinelMonitor(MONITOR_MASTER_NAME, MASTER_IP,
master.getPort(), 1);
assertEquals("OK", result);
// already monitored
try {
j.sentinelMonitor(MONITOR_MASTER_NAME, MASTER_IP,
master.getPort(), 1);
fail();
} catch (JedisDataException e) {
// pass
}
} finally {
j.close();
}
}
@Test
public void sentinelRemove() {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
try {
ensureMonitored(sentinel, REMOVE_MASTER_NAME, MASTER_IP,
master.getPort(), 1);
String result = j.sentinelRemove(REMOVE_MASTER_NAME);
assertEquals("OK", result);
// not exist
try {
result = j.sentinelRemove(REMOVE_MASTER_NAME);
assertNotEquals("OK", result);
fail();
} catch (JedisDataException e) {
// pass
}
} finally {
j.close();
}
}
@Test
public void sentinelSet() {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
try {
Map<String, String> parameterMap = new HashMap<String, String>();
parameterMap.put("down-after-milliseconds", String.valueOf(1234));
parameterMap.put("parallel-syncs", String.valueOf(3));
parameterMap.put("quorum", String.valueOf(2));
j.sentinelSet(MASTER_NAME, parameterMap);
List<Map<String, String>> masters = j.sentinelMasters();
for (Map<String, String> master : masters) {
if (master.get("name").equals(MASTER_NAME)) {
assertEquals(1234, Integer.parseInt(master
.get("down-after-milliseconds")));
assertEquals(3,
Integer.parseInt(master.get("parallel-syncs")));
assertEquals(2, Integer.parseInt(master.get("quorum")));
}
}
parameterMap.put("quorum", String.valueOf(1));
j.sentinelSet(MASTER_NAME, parameterMap);
} finally {
j.close();
}
}
private void ensureMonitored(HostAndPort sentinel, String masterName,
String ip, int port, int quorum) {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
try {
j.sentinelMonitor(masterName, ip, port, quorum);
} catch (JedisDataException e) {
} finally {
j.close();
}
}
private void ensureRemoved(String masterName) {
Jedis j = new Jedis(sentinel.getHost(), sentinel.getPort());
try {
j.sentinelRemove(masterName);
} catch (JedisDataException e) {
} finally {
j.close();
}
}
} }

View File

@@ -8,6 +8,7 @@ import java.util.Map;
import org.junit.Test; import org.junit.Test;
import redis.clients.jedis.BinaryJedis;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.Protocol; import redis.clients.jedis.Protocol;
@@ -91,4 +92,12 @@ public class JedisTest extends JedisCommandTestBase {
assertEquals("PONG", jedis.ping()); assertEquals("PONG", jedis.ping());
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
} }
@Test
public void checkCloseable() {
jedis.close();
BinaryJedis bj = new BinaryJedis("localhost");
bj.connect();
bj.close();
}
} }

View File

@@ -8,18 +8,18 @@ import org.junit.Assert;
public abstract class JedisTestBase extends Assert { public abstract class JedisTestBase extends Assert {
protected void assertEquals(List<byte[]> expected, List<byte[]> actual) { protected void assertEquals(List<byte[]> expected, List<byte[]> actual) {
assertEquals(expected.size(), actual.size()); assertEquals(expected.size(), actual.size());
for (int n = 0; n < expected.size(); n++) { for (int n = 0; n < expected.size(); n++) {
assertArrayEquals(expected.get(n), actual.get(n)); assertArrayEquals(expected.get(n), actual.get(n));
} }
} }
protected void assertEquals(Set<byte[]> expected, Set<byte[]> actual) { protected void assertEquals(Set<byte[]> expected, Set<byte[]> actual) {
assertEquals(expected.size(), actual.size()); assertEquals(expected.size(), actual.size());
Iterator<byte[]> iterator = expected.iterator(); Iterator<byte[]> iterator = expected.iterator();
Iterator<byte[]> iterator2 = actual.iterator(); Iterator<byte[]> iterator2 = actual.iterator();
while (iterator.hasNext() || iterator2.hasNext()) { while (iterator.hasNext() || iterator2.hasNext()) {
assertArrayEquals(iterator.next(), iterator2.next()); assertArrayEquals(iterator.next(), iterator2.next());
} }
} }
} }

View File

@@ -15,7 +15,6 @@ import org.junit.Test;
import redis.clients.jedis.HostAndPort; import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.Pipeline; import redis.clients.jedis.Pipeline;
import redis.clients.jedis.PipelineBlock;
import redis.clients.jedis.Response; import redis.clients.jedis.Response;
import redis.clients.jedis.Tuple; import redis.clients.jedis.Tuple;
import redis.clients.jedis.exceptions.JedisDataException; import redis.clients.jedis.exceptions.JedisDataException;
@@ -27,307 +26,351 @@ public class PipeliningTest extends Assert {
@Before @Before
public void setUp() throws Exception { public void setUp() throws Exception {
jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500); jedis = new Jedis(hnp.getHost(), hnp.getPort(), 500);
jedis.connect(); jedis.connect();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.flushAll(); jedis.flushAll();
} }
@Test @Test
public void pipeline() throws UnsupportedEncodingException { public void pipeline() throws UnsupportedEncodingException {
List<Object> results = jedis.pipelined(new PipelineBlock() { Pipeline p = jedis.pipelined();
public void execute() { p.set("foo", "bar");
set("foo", "bar"); p.get("foo");
get("foo"); List<Object> results = p.syncAndReturnAll();
}
});
assertEquals(2, results.size()); assertEquals(2, results.size());
assertEquals("OK", results.get(0)); assertEquals("OK", results.get(0));
assertEquals("bar", results.get(1)); assertEquals("bar", results.get(1));
Pipeline p = jedis.pipelined();
p.set("foo", "bar");
p.get("foo");
results = p.syncAndReturnAll();
assertEquals(2, results.size());
assertEquals("OK", results.get(0));
assertEquals("bar", results.get(1));
} }
@Test @Test
public void pipelineResponse() { public void pipelineResponse() {
jedis.set("string", "foo"); jedis.set("string", "foo");
jedis.lpush("list", "foo"); jedis.lpush("list", "foo");
jedis.hset("hash", "foo", "bar"); jedis.hset("hash", "foo", "bar");
jedis.zadd("zset", 1, "foo"); jedis.zadd("zset", 1, "foo");
jedis.sadd("set", "foo"); jedis.sadd("set", "foo");
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<String> string = p.get("string"); Response<String> string = p.get("string");
Response<String> list = p.lpop("list"); Response<String> list = p.lpop("list");
Response<String> hash = p.hget("hash", "foo"); Response<String> hash = p.hget("hash", "foo");
Response<Set<String>> zset = p.zrange("zset", 0, -1); Response<Set<String>> zset = p.zrange("zset", 0, -1);
Response<String> set = p.spop("set"); Response<String> set = p.spop("set");
Response<Boolean> blist = p.exists("list"); Response<Boolean> blist = p.exists("list");
Response<Double> zincrby = p.zincrby("zset", 1, "foo"); Response<Double> zincrby = p.zincrby("zset", 1, "foo");
Response<Long> zcard = p.zcard("zset"); Response<Long> zcard = p.zcard("zset");
p.lpush("list", "bar"); p.lpush("list", "bar");
Response<List<String>> lrange = p.lrange("list", 0, -1); Response<List<String>> lrange = p.lrange("list", 0, -1);
Response<Map<String, String>> hgetAll = p.hgetAll("hash"); Response<Map<String, String>> hgetAll = p.hgetAll("hash");
p.sadd("set", "foo"); p.sadd("set", "foo");
Response<Set<String>> smembers = p.smembers("set"); Response<Set<String>> smembers = p.smembers("set");
Response<Set<Tuple>> zrangeWithScores = p.zrangeWithScores("zset", 0, Response<Set<Tuple>> zrangeWithScores = p.zrangeWithScores("zset", 0,
-1); -1);
p.sync(); p.sync();
assertEquals("foo", string.get()); assertEquals("foo", string.get());
assertEquals("foo", list.get()); assertEquals("foo", list.get());
assertEquals("bar", hash.get()); assertEquals("bar", hash.get());
assertEquals("foo", zset.get().iterator().next()); assertEquals("foo", zset.get().iterator().next());
assertEquals("foo", set.get()); assertEquals("foo", set.get());
assertEquals(false, blist.get()); assertEquals(false, blist.get());
assertEquals(Double.valueOf(2), zincrby.get()); assertEquals(Double.valueOf(2), zincrby.get());
assertEquals(Long.valueOf(1), zcard.get()); assertEquals(Long.valueOf(1), zcard.get());
assertEquals(1, lrange.get().size()); assertEquals(1, lrange.get().size());
assertNotNull(hgetAll.get().get("foo")); assertNotNull(hgetAll.get().get("foo"));
assertEquals(1, smembers.get().size()); assertEquals(1, smembers.get().size());
assertEquals(1, zrangeWithScores.get().size()); assertEquals(1, zrangeWithScores.get().size());
} }
@Test @Test
public void pipelineResponseWithData() { public void pipelineResponseWithData() {
jedis.zadd("zset", 1, "foo"); jedis.zadd("zset", 1, "foo");
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<Double> score = p.zscore("zset", "foo"); Response<Double> score = p.zscore("zset", "foo");
p.sync(); p.sync();
assertNotNull(score.get()); assertNotNull(score.get());
} }
@Test @Test
public void pipelineBinarySafeHashCommands() { public void pipelineBinarySafeHashCommands() {
jedis.hset("key".getBytes(), "f1".getBytes(), "v111".getBytes()); jedis.hset("key".getBytes(), "f1".getBytes(), "v111".getBytes());
jedis.hset("key".getBytes(), "f22".getBytes(), "v2222".getBytes()); jedis.hset("key".getBytes(), "f22".getBytes(), "v2222".getBytes());
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<Map<byte[],byte[]>> fmap = p.hgetAll("key".getBytes()); Response<Map<byte[], byte[]>> fmap = p.hgetAll("key".getBytes());
Response<Set<byte[]>> fkeys = p.hkeys("key".getBytes()); Response<Set<byte[]>> fkeys = p.hkeys("key".getBytes());
Response<List<byte[]>> fordered = p.hmget("key".getBytes(), "f22".getBytes(), "f1".getBytes()); Response<List<byte[]>> fordered = p.hmget("key".getBytes(),
Response<List<byte[]>> fvals = p.hvals("key".getBytes()); "f22".getBytes(), "f1".getBytes());
p.sync(); Response<List<byte[]>> fvals = p.hvals("key".getBytes());
p.sync();
assertNotNull(fmap.get()); assertNotNull(fmap.get());
// we have to do these strange contortions because byte[] is not a very good key // we have to do these strange contortions because byte[] is not a very
// for a java Map. It only works with equality (you need the exact key object to retrieve // good key
// the value) I recommend we switch to using ByteBuffer or something similar: // for a java Map. It only works with equality (you need the exact key
// http://stackoverflow.com/questions/1058149/using-a-byte-array-as-hashmap-key-java // object to retrieve
Map<byte[],byte[]> map = fmap.get(); // the value) I recommend we switch to using ByteBuffer or something
Set<byte[]> mapKeys = map.keySet(); // similar:
Iterator<byte[]> iterMap = mapKeys.iterator(); // http://stackoverflow.com/questions/1058149/using-a-byte-array-as-hashmap-key-java
byte[] firstMapKey = iterMap.next(); Map<byte[], byte[]> map = fmap.get();
byte[] secondMapKey = iterMap.next(); Set<byte[]> mapKeys = map.keySet();
assertFalse(iterMap.hasNext()); Iterator<byte[]> iterMap = mapKeys.iterator();
verifyHasBothValues(firstMapKey, secondMapKey, "f1".getBytes(), "f22".getBytes()); byte[] firstMapKey = iterMap.next();
byte[] firstMapValue = map.get(firstMapKey); byte[] secondMapKey = iterMap.next();
byte[] secondMapValue = map.get(secondMapKey); assertFalse(iterMap.hasNext());
verifyHasBothValues(firstMapValue, secondMapValue, "v111".getBytes(), "v2222".getBytes()); verifyHasBothValues(firstMapKey, secondMapKey, "f1".getBytes(),
"f22".getBytes());
byte[] firstMapValue = map.get(firstMapKey);
byte[] secondMapValue = map.get(secondMapKey);
verifyHasBothValues(firstMapValue, secondMapValue, "v111".getBytes(),
"v2222".getBytes());
assertNotNull(fkeys.get()); assertNotNull(fkeys.get());
Iterator<byte[]> iter = fkeys.get().iterator(); Iterator<byte[]> iter = fkeys.get().iterator();
byte[] firstKey = iter.next(); byte[] firstKey = iter.next();
byte[] secondKey = iter.next(); byte[] secondKey = iter.next();
assertFalse(iter.hasNext()); assertFalse(iter.hasNext());
verifyHasBothValues(firstKey, secondKey, "f1".getBytes(), "f22".getBytes()); verifyHasBothValues(firstKey, secondKey, "f1".getBytes(),
"f22".getBytes());
assertNotNull(fordered.get()); assertNotNull(fordered.get());
assertArrayEquals("v2222".getBytes(), fordered.get().get(0)); assertArrayEquals("v2222".getBytes(), fordered.get().get(0));
assertArrayEquals("v111".getBytes(), fordered.get().get(1)); assertArrayEquals("v111".getBytes(), fordered.get().get(1));
assertNotNull(fvals.get()); assertNotNull(fvals.get());
assertEquals(2, fvals.get().size()); assertEquals(2, fvals.get().size());
byte[] firstValue = fvals.get().get(0); byte[] firstValue = fvals.get().get(0);
byte[] secondValue = fvals.get().get(1); byte[] secondValue = fvals.get().get(1);
verifyHasBothValues(firstValue, secondValue, "v111".getBytes(), "v2222".getBytes()); verifyHasBothValues(firstValue, secondValue, "v111".getBytes(),
"v2222".getBytes());
} }
private void verifyHasBothValues(byte[] firstKey, byte[] secondKey, byte[] value1, byte[] value2) { private void verifyHasBothValues(byte[] firstKey, byte[] secondKey,
assertFalse(Arrays.equals(firstKey, secondKey)); byte[] value1, byte[] value2) {
assertTrue(Arrays.equals(firstKey, value1) || Arrays.equals(firstKey, value2)); assertFalse(Arrays.equals(firstKey, secondKey));
assertTrue(Arrays.equals(secondKey, value1) || Arrays.equals(secondKey, value2)); assertTrue(Arrays.equals(firstKey, value1)
|| Arrays.equals(firstKey, value2));
assertTrue(Arrays.equals(secondKey, value1)
|| Arrays.equals(secondKey, value2));
} }
@Test @Test
public void pipelineSelect() { public void pipelineSelect() {
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
p.select(1); p.select(1);
p.sync(); p.sync();
} }
@Test @Test
public void pipelineResponseWithoutData() { public void pipelineResponseWithoutData() {
jedis.zadd("zset", 1, "foo"); jedis.zadd("zset", 1, "foo");
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<Double> score = p.zscore("zset", "bar"); Response<Double> score = p.zscore("zset", "bar");
p.sync(); p.sync();
assertNull(score.get()); assertNull(score.get());
} }
@Test(expected = JedisDataException.class) @Test(expected = JedisDataException.class)
public void pipelineResponseWithinPipeline() { public void pipelineResponseWithinPipeline() {
jedis.set("string", "foo"); jedis.set("string", "foo");
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<String> string = p.get("string"); Response<String> string = p.get("string");
string.get(); string.get();
p.sync(); p.sync();
} }
@Test @Test
public void pipelineWithPubSub() { public void pipelineWithPubSub() {
Pipeline pipelined = jedis.pipelined(); Pipeline pipelined = jedis.pipelined();
Response<Long> p1 = pipelined.publish("foo", "bar"); Response<Long> p1 = pipelined.publish("foo", "bar");
Response<Long> p2 = pipelined.publish("foo".getBytes(), "bar" Response<Long> p2 = pipelined.publish("foo".getBytes(),
.getBytes()); "bar".getBytes());
pipelined.sync(); pipelined.sync();
assertEquals(0, p1.get().longValue()); assertEquals(0, p1.get().longValue());
assertEquals(0, p2.get().longValue()); assertEquals(0, p2.get().longValue());
} }
@Test @Test
public void canRetrieveUnsetKey() { public void canRetrieveUnsetKey() {
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<String> shouldNotExist = p.get(UUID.randomUUID().toString()); Response<String> shouldNotExist = p.get(UUID.randomUUID().toString());
p.sync(); p.sync();
assertNull(shouldNotExist.get()); assertNull(shouldNotExist.get());
} }
@Test @Test
public void piplineWithError(){ public void piplineWithError() {
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
p.set("foo", "bar"); p.set("foo", "bar");
Response<Set<String>> error = p.smembers("foo"); Response<Set<String>> error = p.smembers("foo");
Response<String> r = p.get("foo"); Response<String> r = p.get("foo");
p.sync(); p.sync();
try{ try {
error.get(); error.get();
fail(); fail();
}catch(JedisDataException e){ } catch (JedisDataException e) {
//that is fine we should be here // that is fine we should be here
} }
assertEquals(r.get(), "bar"); assertEquals(r.get(), "bar");
} }
@Test @Test
public void multi(){ public void multi() {
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
p.multi(); p.multi();
Response<Long> r1 = p.hincrBy("a", "f1", -1); Response<Long> r1 = p.hincrBy("a", "f1", -1);
Response<Long> r2 = p.hincrBy("a", "f1", -2); Response<Long> r2 = p.hincrBy("a", "f1", -2);
Response<List<Object>> r3 = p.exec(); Response<List<Object>> r3 = p.exec();
List<Object> result = p.syncAndReturnAll(); List<Object> result = p.syncAndReturnAll();
assertEquals(new Long(-1), r1.get()); assertEquals(new Long(-1), r1.get());
assertEquals(new Long(-3), r2.get()); assertEquals(new Long(-3), r2.get());
assertEquals(4, result.size()); assertEquals(4, result.size());
assertEquals("OK", result.get(0)); assertEquals("OK", result.get(0));
assertEquals("QUEUED", result.get(1)); assertEquals("QUEUED", result.get(1));
assertEquals("QUEUED", result.get(2)); assertEquals("QUEUED", result.get(2));
//4th result is a list with the results from the multi // 4th result is a list with the results from the multi
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
List<Object> multiResult = (List<Object>) result.get(3); List<Object> multiResult = (List<Object>) result.get(3);
assertEquals(new Long(-1), multiResult.get(0)); assertEquals(new Long(-1), multiResult.get(0));
assertEquals(new Long(-3), multiResult.get(1)); assertEquals(new Long(-3), multiResult.get(1));
assertEquals(new Long(-1), r3.get().get(0)); assertEquals(new Long(-1), r3.get().get(0));
assertEquals(new Long(-3), r3.get().get(1)); assertEquals(new Long(-3), r3.get().get(1));
} }
@Test
public void multiWithSync() {
jedis.set("foo", "314");
jedis.set("bar", "foo");
jedis.set("hello", "world");
Pipeline p = jedis.pipelined();
Response<String> r1 = p.get("bar");
p.multi();
Response<String> r2 = p.get("foo");
p.exec();
Response<String> r3 = p.get("hello");
p.sync();
// before multi
assertEquals("foo", r1.get());
// It should be readable whether exec's response was built or not
assertEquals("314", r2.get());
// after multi
assertEquals("world", r3.get());
}
@Test(expected = JedisDataException.class)
public void pipelineExecShoudThrowJedisDataExceptionWhenNotInMulti() {
Pipeline pipeline = jedis.pipelined();
pipeline.exec();
}
@Test(expected = JedisDataException.class)
public void pipelineDiscardShoudThrowJedisDataExceptionWhenNotInMulti() {
Pipeline pipeline = jedis.pipelined();
pipeline.discard();
}
@Test(expected = JedisDataException.class)
public void pipelineMultiShoudThrowJedisDataExceptionWhenAlreadyInMulti() {
Pipeline pipeline = jedis.pipelined();
pipeline.multi();
pipeline.set("foo", "3");
pipeline.multi();
}
@Test @Test
public void testDiscardInPipeline() { public void testDiscardInPipeline() {
Pipeline pipeline = jedis.pipelined(); Pipeline pipeline = jedis.pipelined();
pipeline.multi(); pipeline.multi();
pipeline.set("foo", "bar"); pipeline.set("foo", "bar");
Response<String> discard = pipeline.discard(); Response<String> discard = pipeline.discard();
Response<String> get = pipeline.get("foo"); Response<String> get = pipeline.get("foo");
pipeline.sync(); pipeline.sync();
discard.get(); discard.get();
get.get(); get.get();
} }
@Test @Test
public void testEval() { public void testEval() {
String script = "return 'success!'"; String script = "return 'success!'";
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<String> result = p.eval(script); Response<String> result = p.eval(script);
p.sync(); p.sync();
assertEquals("success!", result.get()); assertEquals("success!", result.get());
} }
@Test @Test
public void testEvalKeyAndArg() { public void testEvalKeyAndArg() {
String key = "test"; String key = "test";
String arg = "3"; String arg = "3";
String script = "redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])"; String script = "redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])";
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
p.set(key, "0"); p.set(key, "0");
Response<String> result0 = p.eval(script, Arrays.asList(key), Arrays.asList(arg)); Response<String> result0 = p.eval(script, Arrays.asList(key),
p.incr(key); Arrays.asList(arg));
Response<String> result1 = p.eval(script, Arrays.asList(key), Arrays.asList(arg)); p.incr(key);
Response<String> result2 = p.get(key); Response<String> result1 = p.eval(script, Arrays.asList(key),
p.sync(); Arrays.asList(arg));
Response<String> result2 = p.get(key);
p.sync();
assertNull(result0.get()); assertNull(result0.get());
assertNull(result1.get()); assertNull(result1.get());
assertEquals("13", result2.get()); assertEquals("13", result2.get());
} }
@Test @Test
public void testEvalsha() { public void testEvalsha() {
String script = "return 'success!'"; String script = "return 'success!'";
String sha1 = jedis.scriptLoad(script); String sha1 = jedis.scriptLoad(script);
assertTrue(jedis.scriptExists(sha1)); assertTrue(jedis.scriptExists(sha1));
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
Response<String> result = p.evalsha(sha1); Response<String> result = p.evalsha(sha1);
p.sync(); p.sync();
assertEquals("success!", result.get()); assertEquals("success!", result.get());
} }
@Test @Test
public void testEvalshaKeyAndArg() { public void testEvalshaKeyAndArg() {
String key = "test"; String key = "test";
String arg = "3"; String arg = "3";
String script = "redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])"; String script = "redis.call('INCRBY', KEYS[1], ARGV[1]) redis.call('INCRBY', KEYS[1], ARGV[1])";
String sha1 = jedis.scriptLoad(script); String sha1 = jedis.scriptLoad(script);
assertTrue(jedis.scriptExists(sha1)); assertTrue(jedis.scriptExists(sha1));
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
p.set(key, "0"); p.set(key, "0");
Response<String> result0 = p.evalsha(sha1, Arrays.asList(key), Arrays.asList(arg)); Response<String> result0 = p.evalsha(sha1, Arrays.asList(key),
p.incr(key); Arrays.asList(arg));
Response<String> result1 = p.evalsha(sha1, Arrays.asList(key), Arrays.asList(arg)); p.incr(key);
Response<String> result2 = p.get(key); Response<String> result1 = p.evalsha(sha1, Arrays.asList(key),
p.sync(); Arrays.asList(arg));
Response<String> result2 = p.get(key);
p.sync();
assertNull(result0.get()); assertNull(result0.get());
assertNull(result1.get()); assertNull(result1.get());
assertEquals("13", result2.get()); assertEquals("13", result2.get());
} }
} }

View File

@@ -4,6 +4,7 @@ import java.io.BufferedInputStream;
import java.io.ByteArrayInputStream; import java.io.ByteArrayInputStream;
import java.io.IOException; import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream;
import java.io.PipedInputStream; import java.io.PipedInputStream;
import java.io.PipedOutputStream; import java.io.PipedOutputStream;
import java.util.ArrayList; import java.util.ArrayList;
@@ -19,86 +20,108 @@ import redis.clients.util.SafeEncoder;
public class ProtocolTest extends JedisTestBase { public class ProtocolTest extends JedisTestBase {
@Test @Test
public void buildACommand() throws IOException { public void buildACommand() throws IOException {
PipedInputStream pis = new PipedInputStream(); PipedInputStream pis = new PipedInputStream();
BufferedInputStream bis = new BufferedInputStream(pis); BufferedInputStream bis = new BufferedInputStream(pis);
PipedOutputStream pos = new PipedOutputStream(pis); PipedOutputStream pos = new PipedOutputStream(pis);
RedisOutputStream ros = new RedisOutputStream(pos); RedisOutputStream ros = new RedisOutputStream(pos);
Protocol.sendCommand(ros, Protocol.Command.GET, Protocol.sendCommand(ros, Protocol.Command.GET,
"SOMEKEY".getBytes(Protocol.CHARSET)); "SOMEKEY".getBytes(Protocol.CHARSET));
ros.flush(); ros.flush();
pos.close(); pos.close();
String expectedCommand = "*2\r\n$3\r\nGET\r\n$7\r\nSOMEKEY\r\n"; String expectedCommand = "*2\r\n$3\r\nGET\r\n$7\r\nSOMEKEY\r\n";
int b; int b;
StringBuilder sb = new StringBuilder(); StringBuilder sb = new StringBuilder();
while ((b = bis.read()) != -1) { while ((b = bis.read()) != -1) {
sb.append((char) b); sb.append((char) b);
} }
assertEquals(expectedCommand, sb.toString());
}
@Test(expected=IOException.class)
public void writeOverflow() throws IOException {
RedisOutputStream ros = new RedisOutputStream(new OutputStream() {
@Override
public void write(int b) throws IOException {
throw new IOException("thrown exception");
}
});
ros.write(new byte[8191]);
try {
ros.write((byte)'*');
} catch (IOException ioe) {}
ros.write((byte)'*');
assertEquals(expectedCommand, sb.toString());
} }
@Test @Test
public void bulkReply() { public void bulkReply() {
InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes()); InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes());
byte[] response = (byte[]) Protocol.read(new RedisInputStream(is)); byte[] response = (byte[]) Protocol.read(new RedisInputStream(is));
assertArrayEquals(SafeEncoder.encode("foobar"), response); assertArrayEquals(SafeEncoder.encode("foobar"), response);
} }
@Test @Test
public void fragmentedBulkReply() { public void fragmentedBulkReply() {
FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream( FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream(
"$30\r\n012345678901234567890123456789\r\n".getBytes()); "$30\r\n012345678901234567890123456789\r\n".getBytes());
byte[] response = (byte[]) Protocol.read(new RedisInputStream(fis)); byte[] response = (byte[]) Protocol.read(new RedisInputStream(fis));
assertArrayEquals(SafeEncoder.encode("012345678901234567890123456789"), assertArrayEquals(SafeEncoder.encode("012345678901234567890123456789"),
response); response);
} }
@Test @Test
public void nullBulkReply() { public void nullBulkReply() {
InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes()); InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes());
String response = (String) Protocol.read(new RedisInputStream(is)); String response = (String) Protocol.read(new RedisInputStream(is));
assertEquals(null, response); assertEquals(null, response);
} }
@Test @Test
public void singleLineReply() { public void singleLineReply() {
InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes()); InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes());
byte[] response = (byte[]) Protocol.read(new RedisInputStream(is)); byte[] response = (byte[]) Protocol.read(new RedisInputStream(is));
assertArrayEquals(SafeEncoder.encode("OK"), response); assertArrayEquals(SafeEncoder.encode("OK"), response);
} }
@Test @Test
public void integerReply() { public void integerReply() {
InputStream is = new ByteArrayInputStream(":123\r\n".getBytes()); InputStream is = new ByteArrayInputStream(":123\r\n".getBytes());
long response = (Long) Protocol.read(new RedisInputStream(is)); long response = (Long) Protocol.read(new RedisInputStream(is));
assertEquals(123, response); assertEquals(123, response);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void multiBulkReply() { public void multiBulkReply() {
InputStream is = new ByteArrayInputStream( InputStream is = new ByteArrayInputStream(
"*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n" "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n"
.getBytes()); .getBytes());
List<byte[]> response = (List<byte[]>) Protocol List<byte[]> response = (List<byte[]>) Protocol
.read(new RedisInputStream(is)); .read(new RedisInputStream(is));
List<byte[]> expected = new ArrayList<byte[]>(); List<byte[]> expected = new ArrayList<byte[]>();
expected.add(SafeEncoder.encode("foo")); expected.add(SafeEncoder.encode("foo"));
expected.add(SafeEncoder.encode("bar")); expected.add(SafeEncoder.encode("bar"));
expected.add(SafeEncoder.encode("Hello")); expected.add(SafeEncoder.encode("Hello"));
expected.add(SafeEncoder.encode("World")); expected.add(SafeEncoder.encode("World"));
assertEquals(expected, response); assertEquals(expected, response);
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@Test @Test
public void nullMultiBulkReply() { public void nullMultiBulkReply() {
InputStream is = new ByteArrayInputStream("*-1\r\n".getBytes()); InputStream is = new ByteArrayInputStream("*-1\r\n".getBytes());
List<String> response = (List<String>) Protocol List<String> response = (List<String>) Protocol
.read(new RedisInputStream(is)); .read(new RedisInputStream(is));
assertNull(response); assertNull(response);
} }
} }

View File

@@ -14,6 +14,7 @@ import redis.clients.jedis.HostAndPort;
import redis.clients.jedis.Jedis; import redis.clients.jedis.Jedis;
import redis.clients.jedis.JedisShardInfo; import redis.clients.jedis.JedisShardInfo;
import redis.clients.jedis.ShardedJedis; import redis.clients.jedis.ShardedJedis;
import redis.clients.jedis.ShardedJedisPipeline;
import redis.clients.jedis.ShardedJedisPool; import redis.clients.jedis.ShardedJedisPool;
import redis.clients.jedis.exceptions.JedisConnectionException; import redis.clients.jedis.exceptions.JedisConnectionException;
@@ -155,7 +156,7 @@ public class ShardedJedisPoolTest extends Assert {
// items on one shard // items on one shard
// alter shard 1 and recreate pool // alter shard 1 and recreate pool
pool.destroy(); pool.destroy();
shards.set(1, new JedisShardInfo("nohost", 1234)); shards.set(1, new JedisShardInfo("localhost", 1234));
pool = new ShardedJedisPool(redisConfig, shards); pool = new ShardedJedisPool(redisConfig, shards);
jedis = pool.getResource(); jedis = pool.getResource();
Long actual = Long.valueOf(0); Long actual = Long.valueOf(0);
@@ -233,4 +234,69 @@ public class ShardedJedisPoolTest extends Assert {
assertEquals("PONG", jedis.ping()); assertEquals("PONG", jedis.ping());
assertEquals("bar", jedis.get("foo")); assertEquals("bar", jedis.get("foo"));
} }
@Test
public void returnResourceShouldResetState() throws URISyntaxException {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(new URI(
"redis://:foobared@localhost:6380")));
shards.add(new JedisShardInfo(new URI(
"redis://:foobared@localhost:6379")));
ShardedJedisPool pool = new ShardedJedisPool(config, shards);
ShardedJedis jedis = pool.getResource();
jedis.set("pipelined", String.valueOf(0));
jedis.set("pipelined2", String.valueOf(0));
ShardedJedisPipeline pipeline = jedis.pipelined();
pipeline.incr("pipelined");
pipeline.incr("pipelined2");
jedis.resetState();
pipeline = jedis.pipelined();
pipeline.incr("pipelined");
pipeline.incr("pipelined2");
List<Object> results = pipeline.syncAndReturnAll();
assertEquals(2, results.size());
pool.returnResource(jedis);
pool.destroy();
}
@Test
public void checkResourceIsCloseable() throws URISyntaxException {
GenericObjectPoolConfig config = new GenericObjectPoolConfig();
config.setMaxTotal(1);
config.setBlockWhenExhausted(false);
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(new URI(
"redis://:foobared@localhost:6380")));
shards.add(new JedisShardInfo(new URI(
"redis://:foobared@localhost:6379")));
ShardedJedisPool pool = new ShardedJedisPool(config, shards);
ShardedJedis jedis = pool.getResource();
try {
jedis.set("hello", "jedis");
} finally {
jedis.close();
}
ShardedJedis jedis2 = pool.getResource();
try {
assertEquals(jedis, jedis2);
} finally {
jedis2.close();
}
}
} }

View File

@@ -18,286 +18,309 @@ import redis.clients.util.Sharded;
public class ShardedJedisTest extends Assert { public class ShardedJedisTest extends Assert {
private static HostAndPort redis1 = HostAndPortUtil.getRedisServers() private static HostAndPort redis1 = HostAndPortUtil.getRedisServers()
.get(0); .get(0);
private static HostAndPort redis2 = HostAndPortUtil.getRedisServers() private static HostAndPort redis2 = HostAndPortUtil.getRedisServers()
.get(1); .get(1);
private List<String> getKeysDifferentShard(ShardedJedis jedis) { private List<String> getKeysDifferentShard(ShardedJedis jedis) {
List<String> ret = new ArrayList<String>(); List<String> ret = new ArrayList<String>();
JedisShardInfo first = jedis.getShardInfo("a0"); JedisShardInfo first = jedis.getShardInfo("a0");
ret.add("a0"); ret.add("a0");
for (int i = 1; i < 100; ++i) { for (int i = 1; i < 100; ++i) {
JedisShardInfo actual = jedis.getShardInfo("a" + i); JedisShardInfo actual = jedis.getShardInfo("a" + i);
if (actual != first) { if (actual != first) {
ret.add("a" + i); ret.add("a" + i);
break; break;
} }
} }
return ret; return ret;
} }
@Test @Test
public void checkSharding() { public void checkSharding() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));
shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));
ShardedJedis jedis = new ShardedJedis(shards); ShardedJedis jedis = new ShardedJedis(shards);
List<String> keys = getKeysDifferentShard(jedis); List<String> keys = getKeysDifferentShard(jedis);
JedisShardInfo s1 = jedis.getShardInfo(keys.get(0)); JedisShardInfo s1 = jedis.getShardInfo(keys.get(0));
JedisShardInfo s2 = jedis.getShardInfo(keys.get(1)); JedisShardInfo s2 = jedis.getShardInfo(keys.get(1));
assertNotSame(s1, s2); assertNotSame(s1, s2);
} }
@Test @Test
public void trySharding() { public void trySharding() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort()); JedisShardInfo si = new JedisShardInfo(redis1.getHost(),
si.setPassword("foobared"); redis1.getPort());
shards.add(si); si.setPassword("foobared");
si = new JedisShardInfo(redis2.getHost(), redis2.getPort()); shards.add(si);
si.setPassword("foobared"); si = new JedisShardInfo(redis2.getHost(), redis2.getPort());
shards.add(si); si.setPassword("foobared");
ShardedJedis jedis = new ShardedJedis(shards); shards.add(si);
jedis.set("a", "bar"); ShardedJedis jedis = new ShardedJedis(shards);
JedisShardInfo s1 = jedis.getShardInfo("a"); jedis.set("a", "bar");
jedis.set("b", "bar1"); JedisShardInfo s1 = jedis.getShardInfo("a");
JedisShardInfo s2 = jedis.getShardInfo("b"); jedis.set("b", "bar1");
jedis.disconnect(); JedisShardInfo s2 = jedis.getShardInfo("b");
jedis.disconnect();
Jedis j = new Jedis(s1.getHost(), s1.getPort()); Jedis j = new Jedis(s1.getHost(), s1.getPort());
j.auth("foobared"); j.auth("foobared");
assertEquals("bar", j.get("a")); assertEquals("bar", j.get("a"));
j.disconnect(); j.disconnect();
j = new Jedis(s2.getHost(), s2.getPort()); j = new Jedis(s2.getHost(), s2.getPort());
j.auth("foobared"); j.auth("foobared");
assertEquals("bar1", j.get("b")); assertEquals("bar1", j.get("b"));
j.disconnect(); j.disconnect();
} }
@Test @Test
public void tryShardingWithMurmure() { public void tryShardingWithMurmure() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
JedisShardInfo si = new JedisShardInfo(redis1.getHost(), redis1.getPort()); JedisShardInfo si = new JedisShardInfo(redis1.getHost(),
si.setPassword("foobared"); redis1.getPort());
shards.add(si); si.setPassword("foobared");
si = new JedisShardInfo(redis2.getHost(), redis2.getPort()); shards.add(si);
si.setPassword("foobared"); si = new JedisShardInfo(redis2.getHost(), redis2.getPort());
shards.add(si); si.setPassword("foobared");
ShardedJedis jedis = new ShardedJedis(shards, Hashing.MURMUR_HASH); shards.add(si);
jedis.set("a", "bar"); ShardedJedis jedis = new ShardedJedis(shards, Hashing.MURMUR_HASH);
JedisShardInfo s1 = jedis.getShardInfo("a"); jedis.set("a", "bar");
jedis.set("b", "bar1"); JedisShardInfo s1 = jedis.getShardInfo("a");
JedisShardInfo s2 = jedis.getShardInfo("b"); jedis.set("b", "bar1");
jedis.disconnect(); JedisShardInfo s2 = jedis.getShardInfo("b");
jedis.disconnect();
Jedis j = new Jedis(s1.getHost(), s1.getPort()); Jedis j = new Jedis(s1.getHost(), s1.getPort());
j.auth("foobared"); j.auth("foobared");
assertEquals("bar", j.get("a")); assertEquals("bar", j.get("a"));
j.disconnect(); j.disconnect();
j = new Jedis(s2.getHost(), s2.getPort()); j = new Jedis(s2.getHost(), s2.getPort());
j.auth("foobared"); j.auth("foobared");
assertEquals("bar1", j.get("b")); assertEquals("bar1", j.get("b"));
j.disconnect(); j.disconnect();
} }
@Test @Test
public void checkKeyTags() { public void checkKeyTags() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));
shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));
ShardedJedis jedis = new ShardedJedis(shards, ShardedJedis jedis = new ShardedJedis(shards,
ShardedJedis.DEFAULT_KEY_TAG_PATTERN); ShardedJedis.DEFAULT_KEY_TAG_PATTERN);
assertEquals(jedis.getKeyTag("foo"), "foo"); assertEquals(jedis.getKeyTag("foo"), "foo");
assertEquals(jedis.getKeyTag("foo{bar}"), "bar"); assertEquals(jedis.getKeyTag("foo{bar}"), "bar");
assertEquals(jedis.getKeyTag("foo{bar}}"), "bar"); // default pattern is assertEquals(jedis.getKeyTag("foo{bar}}"), "bar"); // default pattern is
// non greedy // non greedy
assertEquals(jedis.getKeyTag("{bar}foo"), "bar"); // Key tag may appear assertEquals(jedis.getKeyTag("{bar}foo"), "bar"); // Key tag may appear
// anywhere // anywhere
assertEquals(jedis.getKeyTag("f{bar}oo"), "bar"); // Key tag may appear assertEquals(jedis.getKeyTag("f{bar}oo"), "bar"); // Key tag may appear
// anywhere // anywhere
JedisShardInfo s1 = jedis.getShardInfo("abc{bar}"); JedisShardInfo s1 = jedis.getShardInfo("abc{bar}");
JedisShardInfo s2 = jedis.getShardInfo("foo{bar}"); JedisShardInfo s2 = jedis.getShardInfo("foo{bar}");
assertSame(s1, s2); assertSame(s1, s2);
List<String> keys = getKeysDifferentShard(jedis); List<String> keys = getKeysDifferentShard(jedis);
JedisShardInfo s3 = jedis.getShardInfo(keys.get(0)); JedisShardInfo s3 = jedis.getShardInfo(keys.get(0));
JedisShardInfo s4 = jedis.getShardInfo(keys.get(1)); JedisShardInfo s4 = jedis.getShardInfo(keys.get(1));
assertNotSame(s3, s4); assertNotSame(s3, s4);
ShardedJedis jedis2 = new ShardedJedis(shards); ShardedJedis jedis2 = new ShardedJedis(shards);
assertEquals(jedis2.getKeyTag("foo"), "foo"); assertEquals(jedis2.getKeyTag("foo"), "foo");
assertNotSame(jedis2.getKeyTag("foo{bar}"), "bar"); assertNotSame(jedis2.getKeyTag("foo{bar}"), "bar");
JedisShardInfo s5 = jedis2.getShardInfo(keys.get(0) + "{bar}"); JedisShardInfo s5 = jedis2.getShardInfo(keys.get(0) + "{bar}");
JedisShardInfo s6 = jedis2.getShardInfo(keys.get(1) + "{bar}"); JedisShardInfo s6 = jedis2.getShardInfo(keys.get(1) + "{bar}");
assertNotSame(s5, s6); assertNotSame(s5, s6);
} }
@Test @Test
public void shardedPipeline() { public void shardedPipeline() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort())); shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));
shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort())); shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));
shards.get(0).setPassword("foobared"); shards.get(0).setPassword("foobared");
shards.get(1).setPassword("foobared"); shards.get(1).setPassword("foobared");
ShardedJedis jedis = new ShardedJedis(shards); ShardedJedis jedis = new ShardedJedis(shards);
final List<String> keys = getKeysDifferentShard(jedis); final List<String> keys = getKeysDifferentShard(jedis);
jedis.set(keys.get(0), "a"); jedis.set(keys.get(0), "a");
jedis.set(keys.get(1), "b"); jedis.set(keys.get(1), "b");
assertNotSame(jedis.getShard(keys.get(0)), jedis.getShard(keys.get(1))); assertNotSame(jedis.getShard(keys.get(0)), jedis.getShard(keys.get(1)));
List<Object> results = jedis.pipelined(new ShardedJedisPipeline() { List<Object> results = jedis.pipelined(new ShardedJedisPipeline() {
public void execute() { public void execute() {
get(keys.get(0)); get(keys.get(0));
get(keys.get(1)); get(keys.get(1));
} }
}); });
List<Object> expected = new ArrayList<Object>(2); List<Object> expected = new ArrayList<Object>(2);
expected.add(SafeEncoder.encode("a")); expected.add(SafeEncoder.encode("a"));
expected.add(SafeEncoder.encode("b")); expected.add(SafeEncoder.encode("b"));
assertEquals(2, results.size()); assertEquals(2, results.size());
assertArrayEquals(SafeEncoder.encode("a"), (byte[]) results.get(0)); assertArrayEquals(SafeEncoder.encode("a"), (byte[]) results.get(0));
assertArrayEquals(SafeEncoder.encode("b"), (byte[]) results.get(1)); assertArrayEquals(SafeEncoder.encode("b"), (byte[]) results.get(1));
} }
@Test @Test
public void testMD5Sharding() { public void testMD5Sharding() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2));
Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(
shards, Hashing.MD5); shards, Hashing.MD5);
int shard_6379 = 0; int shard_6379 = 0;
int shard_6380 = 0; int shard_6380 = 0;
int shard_6381 = 0; int shard_6381 = 0;
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer
.toString(i)); .toString(i));
switch (jedisShardInfo.getPort()) { switch (jedisShardInfo.getPort()) {
case 6379: case 6379:
shard_6379++; shard_6379++;
break; break;
case 6380: case 6380:
shard_6380++; shard_6380++;
break; break;
case 6381: case 6381:
shard_6381++; shard_6381++;
break; break;
default: default:
fail("Attempting to use a non-defined shard!!:" fail("Attempting to use a non-defined shard!!:"
+ jedisShardInfo); + jedisShardInfo);
break; break;
} }
} }
assertTrue(shard_6379 > 300 && shard_6379 < 400); assertTrue(shard_6379 > 300 && shard_6379 < 400);
assertTrue(shard_6380 > 300 && shard_6380 < 400); assertTrue(shard_6380 > 300 && shard_6380 < 400);
assertTrue(shard_6381 > 300 && shard_6381 < 400); assertTrue(shard_6381 > 300 && shard_6381 < 400);
} }
@Test @Test
public void testMurmurSharding() { public void testMurmurSharding() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2));
Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(
shards, Hashing.MURMUR_HASH); shards, Hashing.MURMUR_HASH);
int shard_6379 = 0; int shard_6379 = 0;
int shard_6380 = 0; int shard_6380 = 0;
int shard_6381 = 0; int shard_6381 = 0;
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer
.toString(i)); .toString(i));
switch (jedisShardInfo.getPort()) { switch (jedisShardInfo.getPort()) {
case 6379: case 6379:
shard_6379++; shard_6379++;
break; break;
case 6380: case 6380:
shard_6380++; shard_6380++;
break; break;
case 6381: case 6381:
shard_6381++; shard_6381++;
break; break;
default: default:
fail("Attempting to use a non-defined shard!!:" fail("Attempting to use a non-defined shard!!:"
+ jedisShardInfo); + jedisShardInfo);
break; break;
} }
} }
assertTrue(shard_6379 > 300 && shard_6379 < 400); assertTrue(shard_6379 > 300 && shard_6379 < 400);
assertTrue(shard_6380 > 300 && shard_6380 < 400); assertTrue(shard_6380 > 300 && shard_6380 < 400);
assertTrue(shard_6381 > 300 && shard_6381 < 400); assertTrue(shard_6381 > 300 && shard_6381 < 400);
} }
@Test @Test
public void testMasterSlaveShardingConsistency() { public void testMasterSlaveShardingConsistency() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2)); shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2));
Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(
shards, Hashing.MURMUR_HASH); shards, Hashing.MURMUR_HASH);
List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3);
otherShards.add(new JedisShardInfo("otherhost", Protocol.DEFAULT_PORT)); otherShards.add(new JedisShardInfo("otherhost", Protocol.DEFAULT_PORT));
otherShards.add(new JedisShardInfo("otherhost", otherShards.add(new JedisShardInfo("otherhost",
Protocol.DEFAULT_PORT + 1)); Protocol.DEFAULT_PORT + 1));
otherShards.add(new JedisShardInfo("otherhost", otherShards.add(new JedisShardInfo("otherhost",
Protocol.DEFAULT_PORT + 2)); Protocol.DEFAULT_PORT + 2));
Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>(
otherShards, Hashing.MURMUR_HASH); otherShards, Hashing.MURMUR_HASH);
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer
.toString(i)); .toString(i));
JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer
.toString(i)); .toString(i));
assertEquals(shards.indexOf(jedisShardInfo), otherShards assertEquals(shards.indexOf(jedisShardInfo),
.indexOf(jedisShardInfo2)); otherShards.indexOf(jedisShardInfo2));
} }
} }
@Test @Test
public void testMasterSlaveShardingConsistencyWithShardNaming() { public void testMasterSlaveShardingConsistencyWithShardNaming() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(3);
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT, shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT,
"HOST1:1234")); "HOST1:1234"));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1, shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 1,
"HOST2:1234")); "HOST2:1234"));
shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2, shards.add(new JedisShardInfo("localhost", Protocol.DEFAULT_PORT + 2,
"HOST3:1234")); "HOST3:1234"));
Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded = new Sharded<Jedis, JedisShardInfo>(
shards, Hashing.MURMUR_HASH); shards, Hashing.MURMUR_HASH);
List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3); List<JedisShardInfo> otherShards = new ArrayList<JedisShardInfo>(3);
otherShards.add(new JedisShardInfo("otherhost", Protocol.DEFAULT_PORT, otherShards.add(new JedisShardInfo("otherhost", Protocol.DEFAULT_PORT,
"HOST2:1234")); "HOST2:1234"));
otherShards.add(new JedisShardInfo("otherhost", otherShards.add(new JedisShardInfo("otherhost",
Protocol.DEFAULT_PORT + 1, "HOST3:1234")); Protocol.DEFAULT_PORT + 1, "HOST3:1234"));
otherShards.add(new JedisShardInfo("otherhost", otherShards.add(new JedisShardInfo("otherhost",
Protocol.DEFAULT_PORT + 2, "HOST1:1234")); Protocol.DEFAULT_PORT + 2, "HOST1:1234"));
Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>( Sharded<Jedis, JedisShardInfo> sharded2 = new Sharded<Jedis, JedisShardInfo>(
otherShards, Hashing.MURMUR_HASH); otherShards, Hashing.MURMUR_HASH);
for (int i = 0; i < 1000; i++) { for (int i = 0; i < 1000; i++) {
JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer JedisShardInfo jedisShardInfo = sharded.getShardInfo(Integer
.toString(i)); .toString(i));
JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer JedisShardInfo jedisShardInfo2 = sharded2.getShardInfo(Integer
.toString(i)); .toString(i));
assertEquals(jedisShardInfo.getName(), jedisShardInfo2.getName()); assertEquals(jedisShardInfo.getName(), jedisShardInfo2.getName());
} }
} }
@Test
public void checkCloseable() {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
shards.add(new JedisShardInfo(redis1.getHost(), redis1.getPort()));
shards.add(new JedisShardInfo(redis2.getHost(), redis2.getPort()));
shards.get(0).setPassword("foobared");
shards.get(1).setPassword("foobared");
ShardedJedis jedisShard = new ShardedJedis(shards);
try {
jedisShard.set("shard_closeable", "true");
} finally {
jedisShard.close();
}
for (Jedis jedis : jedisShard.getAllShards()) {
assertTrue(!jedis.isConnected());
}
}
} }

View File

@@ -9,7 +9,7 @@ import redis.clients.jedis.Jedis;
import redis.clients.jedis.tests.HostAndPortUtil; import redis.clients.jedis.tests.HostAndPortUtil;
public class GetSetBenchmark { public class GetSetBenchmark {
private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0);
private static final int TOTAL_OPERATIONS = 100000; private static final int TOTAL_OPERATIONS = 100000;
public static void main(String[] args) throws UnknownHostException, public static void main(String[] args) throws UnknownHostException,

View File

@@ -19,32 +19,33 @@ public class HashingBenchmark {
private static final int TOTAL_OPERATIONS = 100000; private static final int TOTAL_OPERATIONS = 100000;
public static void main(String[] args) throws UnknownHostException, public static void main(String[] args) throws UnknownHostException,
IOException { IOException {
List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>(); List<JedisShardInfo> shards = new ArrayList<JedisShardInfo>();
JedisShardInfo shard = new JedisShardInfo(hnp1.getHost(), hnp1.getPort()); JedisShardInfo shard = new JedisShardInfo(hnp1.getHost(),
shard.setPassword("foobared"); hnp1.getPort());
shards.add(shard); shard.setPassword("foobared");
shard = new JedisShardInfo(hnp2.getHost(), hnp2.getPort()); shards.add(shard);
shard.setPassword("foobared"); shard = new JedisShardInfo(hnp2.getHost(), hnp2.getPort());
shards.add(shard); shard.setPassword("foobared");
ShardedJedis jedis = new ShardedJedis(shards); shards.add(shard);
Collection<Jedis> allShards = jedis.getAllShards(); ShardedJedis jedis = new ShardedJedis(shards);
for (Jedis j : allShards) { Collection<Jedis> allShards = jedis.getAllShards();
j.flushAll(); for (Jedis j : allShards) {
} j.flushAll();
}
long begin = Calendar.getInstance().getTimeInMillis(); long begin = Calendar.getInstance().getTimeInMillis();
for (int n = 0; n <= TOTAL_OPERATIONS; n++) { for (int n = 0; n <= TOTAL_OPERATIONS; n++) {
String key = "foo" + n; String key = "foo" + n;
jedis.set(key, "bar" + n); jedis.set(key, "bar" + n);
jedis.get(key); jedis.get(key);
} }
long elapsed = Calendar.getInstance().getTimeInMillis() - begin; long elapsed = Calendar.getInstance().getTimeInMillis() - begin;
jedis.disconnect(); jedis.disconnect();
System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops"); System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops");
} }
} }

View File

@@ -14,26 +14,26 @@ public class PipelinedGetSetBenchmark {
private static final int TOTAL_OPERATIONS = 200000; private static final int TOTAL_OPERATIONS = 200000;
public static void main(String[] args) throws UnknownHostException, public static void main(String[] args) throws UnknownHostException,
IOException { IOException {
Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort()); Jedis jedis = new Jedis(hnp.getHost(), hnp.getPort());
jedis.connect(); jedis.connect();
jedis.auth("foobared"); jedis.auth("foobared");
jedis.flushAll(); jedis.flushAll();
long begin = Calendar.getInstance().getTimeInMillis(); long begin = Calendar.getInstance().getTimeInMillis();
Pipeline p = jedis.pipelined(); Pipeline p = jedis.pipelined();
for (int n = 0; n <= TOTAL_OPERATIONS; n++) { for (int n = 0; n <= TOTAL_OPERATIONS; n++) {
String key = "foo" + n; String key = "foo" + n;
p.set(key, "bar" + n); p.set(key, "bar" + n);
p.get(key); p.get(key);
} }
p.sync(); p.sync();
long elapsed = Calendar.getInstance().getTimeInMillis() - begin; long elapsed = Calendar.getInstance().getTimeInMillis() - begin;
jedis.disconnect(); jedis.disconnect();
System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops"); System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops");
} }
} }

View File

@@ -10,29 +10,29 @@ public class SafeEncoderBenchmark {
private static final int TOTAL_OPERATIONS = 10000000; private static final int TOTAL_OPERATIONS = 10000000;
public static void main(String[] args) throws UnknownHostException, public static void main(String[] args) throws UnknownHostException,
IOException { IOException {
long begin = Calendar.getInstance().getTimeInMillis(); long begin = Calendar.getInstance().getTimeInMillis();
for (int n = 0; n <= TOTAL_OPERATIONS; n++) { for (int n = 0; n <= TOTAL_OPERATIONS; n++) {
SafeEncoder.encode("foo bar!"); SafeEncoder.encode("foo bar!");
} }
long elapsed = Calendar.getInstance().getTimeInMillis() - begin; long elapsed = Calendar.getInstance().getTimeInMillis() - begin;
System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed)
+ " ops to build byte[]"); + " ops to build byte[]");
begin = Calendar.getInstance().getTimeInMillis(); begin = Calendar.getInstance().getTimeInMillis();
byte[] bytes = "foo bar!".getBytes(); byte[] bytes = "foo bar!".getBytes();
for (int n = 0; n <= TOTAL_OPERATIONS; n++) { for (int n = 0; n <= TOTAL_OPERATIONS; n++) {
SafeEncoder.encode(bytes); SafeEncoder.encode(bytes);
} }
elapsed = Calendar.getInstance().getTimeInMillis() - begin; elapsed = Calendar.getInstance().getTimeInMillis() - begin;
System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed)
+ " ops to build Strings"); + " ops to build Strings");
} }
} }

Some files were not shown because too many files have changed in this diff Show More