├── src ├── test │ ├── resources │ │ └── MySimpson.png │ └── java │ │ └── redis │ │ └── clients │ │ └── jedis │ │ └── tests │ │ ├── BuilderFactoryTest.java │ │ ├── commands │ │ ├── ConnectionHandlingCommandsTest.java │ │ ├── ObjectCommandsTest.java │ │ ├── SlowlogCommandsTest.java │ │ ├── BitCommandsTest.java │ │ ├── JedisCommandTestBase.java │ │ ├── ControlCommandsTest.java │ │ ├── ScriptingCommandsTest.java │ │ ├── StringValuesCommandsTest.java │ │ ├── VariadicCommandsTest.java │ │ └── BinaryValuesCommandsTest.java │ │ ├── JedisTestBase.java │ │ ├── FragmentedByteArrayInputStream.java │ │ ├── benchmark │ │ ├── GetSetBenchmark.java │ │ ├── ShardedBenchmark.java │ │ ├── SafeEncoderBenchmark.java │ │ ├── PipelinedGetSetBenchmark.java │ │ ├── HashingBenchmark.java │ │ └── PoolBenchmark.java │ │ ├── ConnectionTest.java │ │ ├── JedisSentinelTest.java │ │ ├── HostAndPortUtil.java │ │ ├── JedisTest.java │ │ ├── ProtocolTest.java │ │ ├── ShardedJedisPipelineTest.java │ │ └── JedisPoolTest.java └── main │ └── java │ └── redis │ └── clients │ ├── jedis │ ├── BitOP.java │ ├── Builder.java │ ├── PipelineBlock.java │ ├── JedisMonitor.java │ ├── TransactionBlock.java │ ├── exceptions │ │ ├── JedisException.java │ │ ├── JedisDataException.java │ │ └── JedisConnectionException.java │ ├── AdvancedBinaryJedisCommands.java │ ├── AdvancedJedisCommands.java │ ├── ScriptingCommands.java │ ├── BasicCommands.java │ ├── Queable.java │ ├── DebugParams.java │ ├── BinaryScriptingCommands.java │ ├── BasicRedisPipeline.java │ ├── Response.java │ ├── ZParams.java │ ├── MultiKeyCommands.java │ ├── MultiKeyBinaryCommands.java │ ├── MultiKeyCommandsPipeline.java │ ├── MultiKeyBinaryRedisPipeline.java │ ├── Transaction.java │ ├── Tuple.java │ ├── JedisShardInfo.java │ ├── ShardedJedisPipeline.java │ ├── ShardedJedisPool.java │ ├── Pipeline.java │ ├── JedisPoolConfig.java │ ├── BinaryJedisPubSub.java │ ├── JedisPool.java │ ├── SortingParams.java │ ├── JedisPubSub.java │ ├── JedisCommands.java │ ├── BinaryJedisCommands.java │ ├── Protocol.java │ ├── RedisPipeline.java │ └── Connection.java │ └── util │ ├── ShardInfo.java │ ├── Hashing.java │ ├── SafeEncoder.java │ ├── Slowlog.java │ ├── Pool.java │ ├── RedisInputStream.java │ ├── Sharded.java │ ├── JedisByteHashMap.java │ └── MurmurHash.java ├── gradle └── wrapper │ ├── gradle-wrapper.jar │ └── gradle-wrapper.properties ├── .gitignore ├── Makefile ├── LICENSE.txt ├── gradlew.bat ├── pom.xml ├── README.md └── gradlew /src/test/resources/MySimpson.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjw465150/jedis/master/src/test/resources/MySimpson.png -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/wjw465150/jedis/master/gradle/wrapper/gradle-wrapper.jar -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | *.iml 3 | *.ipr 4 | *.iws 5 | .project 6 | .settings/ 7 | .gradle/ 8 | target/ 9 | build/ 10 | bin/ 11 | tags 12 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BitOP.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | public enum BitOP { 4 | AND, 5 | OR, 6 | XOR, 7 | NOT; 8 | } 9 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Builder.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | public abstract class Builder { 4 | public abstract T build(Object data); 5 | } 6 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/PipelineBlock.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | public abstract class PipelineBlock extends Pipeline { 5 | public abstract void execute(); 6 | } 7 | -------------------------------------------------------------------------------- /gradle/wrapper/gradle-wrapper.properties: -------------------------------------------------------------------------------- 1 | #Fri Dec 23 12:54:50 CST 2011 2 | distributionBase=GRADLE_USER_HOME 3 | distributionPath=wrapper/dists 4 | zipStoreBase=GRADLE_USER_HOME 5 | zipStorePath=wrapper/dists 6 | distributionUrl=http\://repo.gradle.org/gradle/distributions/gradle-1.0-milestone-6-bin.zip 7 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/BuilderFactoryTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import org.junit.Assert; 4 | import org.junit.Test; 5 | 6 | import redis.clients.jedis.BuilderFactory; 7 | 8 | public class BuilderFactoryTest extends Assert { 9 | @Test 10 | public void buildDouble() { 11 | Double build = BuilderFactory.DOUBLE.build("1.0".getBytes()); 12 | assertEquals(new Double(1.0), build); 13 | } 14 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/ShardInfo.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | public abstract class ShardInfo { 4 | private int weight; 5 | 6 | public ShardInfo() { 7 | } 8 | 9 | public ShardInfo(int weight) { 10 | this.weight = weight; 11 | } 12 | 13 | public int getWeight() { 14 | return this.weight; 15 | } 16 | 17 | protected abstract T createResource(); 18 | 19 | public abstract String getName(); 20 | } 21 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisMonitor.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | public abstract class JedisMonitor { 4 | protected Client client; 5 | 6 | public void proceed(Client client) { 7 | this.client = client; 8 | this.client.setTimeoutInfinite(); 9 | do { 10 | String command = client.getBulkReply(); 11 | onCommand(command); 12 | } while (client.isConnected()); 13 | } 14 | 15 | public abstract void onCommand(String command); 16 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/TransactionBlock.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import redis.clients.jedis.exceptions.JedisException; 4 | 5 | public abstract class TransactionBlock extends Transaction { 6 | public TransactionBlock(Client client) { 7 | super(client); 8 | } 9 | 10 | public TransactionBlock() { 11 | } 12 | 13 | public abstract void execute() throws JedisException; 14 | 15 | public void setClient(Client client) { 16 | this.client = client; 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/exceptions/JedisException.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.exceptions; 2 | 3 | 4 | public class JedisException extends RuntimeException { 5 | private static final long serialVersionUID = -2946266495682282677L; 6 | 7 | public JedisException(String message) { 8 | super(message); 9 | } 10 | 11 | public JedisException(Throwable e) { 12 | super(e); 13 | } 14 | 15 | public JedisException(String message, Throwable cause) { 16 | super(message, cause); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/exceptions/JedisDataException.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.exceptions; 2 | 3 | public class JedisDataException extends JedisException { 4 | private static final long serialVersionUID = 3878126572474819403L; 5 | 6 | public JedisDataException(String message) { 7 | super(message); 8 | } 9 | 10 | public JedisDataException(Throwable cause) { 11 | super(cause); 12 | } 13 | 14 | public JedisDataException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/exceptions/JedisConnectionException.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.exceptions; 2 | 3 | public class JedisConnectionException extends JedisException { 4 | private static final long serialVersionUID = 3878126572474819403L; 5 | 6 | public JedisConnectionException(String message) { 7 | super(message); 8 | } 9 | 10 | public JedisConnectionException(Throwable cause) { 11 | super(cause); 12 | } 13 | 14 | public JedisConnectionException(String message, Throwable cause) { 15 | super(message, cause); 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/AdvancedBinaryJedisCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | 6 | public interface AdvancedBinaryJedisCommands { 7 | 8 | List configGet(byte[] pattern); 9 | 10 | byte[] configSet(byte[] parameter, byte[] value); 11 | 12 | String slowlogReset(); 13 | 14 | Long slowlogLen(); 15 | 16 | List slowlogGetBinary(); 17 | 18 | List slowlogGetBinary(long entries); 19 | 20 | Long objectRefcount(byte[] key); 21 | 22 | byte[] objectEncoding(byte[] key); 23 | 24 | Long objectIdletime(byte[] key); 25 | } 26 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/AdvancedJedisCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import redis.clients.util.Slowlog; 4 | 5 | import java.util.List; 6 | 7 | 8 | public interface AdvancedJedisCommands { 9 | List configGet(String pattern); 10 | 11 | String configSet(String parameter, String value); 12 | 13 | String slowlogReset(); 14 | 15 | Long slowlogLen(); 16 | 17 | List slowlogGet(); 18 | 19 | List slowlogGet(long entries); 20 | 21 | Long objectRefcount(String string); 22 | 23 | String objectEncoding(String string); 24 | 25 | Long objectIdletime(String string); 26 | } 27 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/ScriptingCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.List; 4 | 5 | public interface ScriptingCommands { 6 | Object eval(String script, int keyCount, String... params); 7 | 8 | Object eval(String script, List keys, List args); 9 | 10 | Object eval(String script); 11 | 12 | Object evalsha(String script); 13 | 14 | Object evalsha(String sha1, List keys, List args); 15 | 16 | Object evalsha(String sha1, int keyCount, String... params); 17 | 18 | Boolean scriptExists(String sha1); 19 | 20 | List scriptExists(String... sha1); 21 | 22 | String scriptLoad(String script); 23 | } 24 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/ConnectionHandlingCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import org.junit.Test; 4 | 5 | import redis.clients.jedis.BinaryJedis; 6 | import redis.clients.jedis.tests.HostAndPortUtil; 7 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 8 | 9 | public class ConnectionHandlingCommandsTest extends JedisCommandTestBase { 10 | protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); 11 | 12 | @Test 13 | public void quit() { 14 | assertEquals("OK", jedis.quit()); 15 | } 16 | 17 | @Test 18 | public void binary_quit() { 19 | BinaryJedis bj = new BinaryJedis(hnp.host); 20 | assertEquals("OK", bj.quit()); 21 | } 22 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BasicCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | public interface BasicCommands { 4 | 5 | String ping(); 6 | 7 | String quit(); 8 | 9 | String flushDB(); 10 | 11 | Long dbSize(); 12 | 13 | String select(int index); 14 | 15 | String flushAll(); 16 | 17 | String auth(String password); 18 | 19 | String save(); 20 | 21 | String bgsave(); 22 | 23 | String bgrewriteaof(); 24 | 25 | Long lastsave(); 26 | 27 | String shutdown(); 28 | 29 | String info(); 30 | 31 | String info(String section); 32 | 33 | String slaveof(String host, int port); 34 | 35 | String slaveofNoOne(); 36 | 37 | Long getDB(); 38 | 39 | String debug(DebugParams params); 40 | 41 | String configResetStat(); 42 | } 43 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Queable.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.LinkedList; 4 | import java.util.Queue; 5 | 6 | public class Queable { 7 | private Queue> pipelinedResponses = new LinkedList>(); 8 | 9 | protected void clean() { 10 | pipelinedResponses.clear(); 11 | } 12 | 13 | protected Response generateResponse(Object data) { 14 | Response response = pipelinedResponses.poll(); 15 | if (response != null) { 16 | response.set(data); 17 | } 18 | return response; 19 | } 20 | 21 | protected Response getResponse(Builder builder) { 22 | Response lr = new Response(builder); 23 | pipelinedResponses.add(lr); 24 | return lr; 25 | } 26 | 27 | } 28 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/DebugParams.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | public class DebugParams { 4 | private String[] command; 5 | 6 | public String[] getCommand() { 7 | return command; 8 | } 9 | 10 | private DebugParams() { 11 | 12 | } 13 | 14 | public static DebugParams SEGFAULT() { 15 | DebugParams debugParams = new DebugParams(); 16 | debugParams.command = new String[] { "SEGFAULT" }; 17 | return debugParams; 18 | } 19 | 20 | public static DebugParams OBJECT(String key) { 21 | DebugParams debugParams = new DebugParams(); 22 | debugParams.command = new String[] { "OBJECT", key }; 23 | return debugParams; 24 | } 25 | 26 | public static DebugParams RELOAD() { 27 | DebugParams debugParams = new DebugParams(); 28 | debugParams.command = new String[] { "RELOAD" }; 29 | return debugParams; 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BinaryScriptingCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | 6 | public interface BinaryScriptingCommands { 7 | 8 | Object eval(byte[] script, byte[] keyCount, byte[]... params); 9 | 10 | Object eval(byte[] script, int keyCount, byte[]... params); 11 | 12 | Object eval(byte[] script, List keys, List args); 13 | 14 | Object eval(byte[] script); 15 | 16 | Object evalsha(byte[] script); 17 | 18 | Object evalsha(byte[] sha1, List keys, List args); 19 | 20 | Object evalsha(byte[] sha1, int keyCount, byte[]... params); 21 | 22 | // TODO: should be Boolean, add singular version 23 | List scriptExists(byte[]... sha1); 24 | 25 | byte[] scriptLoad(byte[] script); 26 | 27 | String scriptFlush(); 28 | 29 | String scriptKill(); 30 | } 31 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BasicRedisPipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | 6 | /** 7 | * Pipelined responses for all of the low level, non key related commands 8 | */ 9 | public interface BasicRedisPipeline { 10 | 11 | Response bgrewriteaof(); 12 | 13 | Response bgsave(); 14 | 15 | Response configGet(String pattern); 16 | 17 | Response configSet(String parameter, String value); 18 | 19 | Response configResetStat(); 20 | 21 | Response save(); 22 | 23 | Response lastsave(); 24 | 25 | Response flushDB(); 26 | 27 | Response flushAll(); 28 | 29 | Response info(); 30 | 31 | Response dbSize(); 32 | 33 | Response shutdown(); 34 | 35 | Response ping(); 36 | 37 | Response select(int index); 38 | } 39 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/JedisTestBase.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.util.Iterator; 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | import org.junit.Assert; 8 | 9 | public abstract class JedisTestBase extends Assert { 10 | protected void assertEquals(List expected, List actual) { 11 | assertEquals(expected.size(), actual.size()); 12 | for (int n = 0; n < expected.size(); n++) { 13 | assertArrayEquals(expected.get(n), actual.get(n)); 14 | } 15 | } 16 | 17 | protected void assertEquals(Set expected, Set actual) { 18 | assertEquals(expected.size(), actual.size()); 19 | Iterator iterator = expected.iterator(); 20 | Iterator iterator2 = actual.iterator(); 21 | while (iterator.hasNext() || iterator2.hasNext()) { 22 | assertArrayEquals(iterator.next(), iterator2.next()); 23 | } 24 | } 25 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/FragmentedByteArrayInputStream.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.io.ByteArrayInputStream; 4 | 5 | /** 6 | * Test class the fragment a byte array for testing purpose. 7 | */ 8 | public class FragmentedByteArrayInputStream extends ByteArrayInputStream { 9 | private int readMethodCallCount = 0; 10 | 11 | public FragmentedByteArrayInputStream(final byte[] buf) { 12 | super(buf); 13 | } 14 | 15 | public synchronized int read(final byte[] b, final int off, final int len) { 16 | readMethodCallCount++; 17 | if (len <= 10) { 18 | // if the len <= 10, return as usual .. 19 | return super.read(b, off, len); 20 | } else { 21 | // else return the first half .. 22 | return super.read(b, off, len / 2); 23 | } 24 | } 25 | 26 | public int getReadMethodCallCount() { 27 | return readMethodCallCount; 28 | } 29 | 30 | } 31 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | define REDIS1_CONF 2 | daemonize yes 3 | port 6379 4 | requirepass foobared 5 | pidfile /tmp/redis1.pid 6 | endef 7 | 8 | define REDIS2_CONF 9 | daemonize yes 10 | port 6380 11 | requirepass foobared 12 | pidfile /tmp/redis2.pid 13 | endef 14 | 15 | 16 | define REDIS_SENTINEL1 17 | port 26379 18 | daemonize yes 19 | sentinel monitor mymaster 127.0.0.1 6379 2 20 | sentinel auth-pass mymaster foobared 21 | sentinel down-after-milliseconds mymaster 5000 22 | sentinel failover-timeout mymaster 900000 23 | sentinel can-failover mymaster yes 24 | sentinel parallel-syncs mymaster 1 25 | pidfile /tmp/sentinel1.pid 26 | endef 27 | 28 | export REDIS1_CONF 29 | export REDIS2_CONF 30 | export REDIS_SENTINEL1 31 | test: 32 | echo "$$REDIS1_CONF" | redis-server - 33 | echo "$$REDIS2_CONF" | redis-server - 34 | echo "$$REDIS_SENTINEL1" | redis-sentinel - 35 | 36 | mvn clean compile test 37 | 38 | kill `cat /tmp/redis1.pid` 39 | kill `cat /tmp/redis2.pid` 40 | kill `cat /tmp/sentinel1.pid` 41 | 42 | .PHONY: test 43 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2010 Jonathan Leibiusky 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/benchmark/GetSetBenchmark.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.benchmark; 2 | 3 | import java.io.IOException; 4 | import java.net.UnknownHostException; 5 | import java.util.Calendar; 6 | 7 | import redis.clients.jedis.Jedis; 8 | import redis.clients.jedis.tests.HostAndPortUtil; 9 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 10 | 11 | public class GetSetBenchmark { 12 | private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); 13 | private static final int TOTAL_OPERATIONS = 100000; 14 | 15 | public static void main(String[] args) throws UnknownHostException, 16 | IOException { 17 | Jedis jedis = new Jedis(hnp.host, hnp.port); 18 | jedis.connect(); 19 | jedis.auth("foobared"); 20 | jedis.flushAll(); 21 | 22 | long begin = Calendar.getInstance().getTimeInMillis(); 23 | 24 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 25 | String key = "foo" + n; 26 | jedis.set(key, "bar" + n); 27 | jedis.get(key); 28 | } 29 | 30 | long elapsed = Calendar.getInstance().getTimeInMillis() - begin; 31 | 32 | jedis.disconnect(); 33 | 34 | System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops"); 35 | } 36 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Response.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import redis.clients.jedis.exceptions.JedisDataException; 4 | 5 | public class Response { 6 | protected T response = null; 7 | private boolean built = false; 8 | private boolean set = false; 9 | private Builder builder; 10 | private Object data; 11 | 12 | public Response(Builder b) { 13 | this.builder = b; 14 | } 15 | 16 | public void set(Object data) { 17 | this.data = data; 18 | set = true; 19 | } 20 | 21 | public T get() { 22 | if (!set) { 23 | throw new JedisDataException( 24 | "Please close pipeline or multi block before calling this method."); 25 | } 26 | if (!built) { 27 | if(data != null ){ 28 | if (data instanceof JedisDataException){ 29 | throw new JedisDataException((JedisDataException)data); 30 | } 31 | response = builder.build(data); 32 | } 33 | this.data = null; 34 | built = true; 35 | } 36 | return response; 37 | } 38 | 39 | public String toString() { 40 | return "Response " + builder.toString(); 41 | } 42 | 43 | } 44 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/ZParams.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import static redis.clients.jedis.Protocol.Keyword.AGGREGATE; 4 | import static redis.clients.jedis.Protocol.Keyword.WEIGHTS; 5 | 6 | import java.util.ArrayList; 7 | import java.util.Collection; 8 | import java.util.Collections; 9 | import java.util.List; 10 | 11 | import redis.clients.util.SafeEncoder; 12 | 13 | public class ZParams { 14 | public enum Aggregate { 15 | SUM, MIN, MAX; 16 | 17 | public final byte[] raw; 18 | 19 | Aggregate() { 20 | raw = SafeEncoder.encode(name()); 21 | } 22 | } 23 | 24 | private List params = new ArrayList(); 25 | 26 | public ZParams weights(final int... weights) { 27 | params.add(WEIGHTS.raw); 28 | for (final int weight : weights) { 29 | params.add(Protocol.toByteArray(weight)); 30 | } 31 | 32 | return this; 33 | } 34 | 35 | public Collection getParams() { 36 | return Collections.unmodifiableCollection(params); 37 | } 38 | 39 | public ZParams aggregate(final Aggregate aggregate) { 40 | params.add(AGGREGATE.raw); 41 | params.add(aggregate.raw); 42 | return this; 43 | } 44 | } 45 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/ConnectionTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import org.junit.After; 4 | import org.junit.Assert; 5 | import org.junit.Before; 6 | import org.junit.Test; 7 | 8 | import redis.clients.jedis.Connection; 9 | import redis.clients.jedis.exceptions.JedisConnectionException; 10 | 11 | public class ConnectionTest extends Assert { 12 | private Connection client; 13 | 14 | @Before 15 | public void setUp() throws Exception { 16 | client = new Connection(); 17 | } 18 | 19 | @After 20 | public void tearDown() throws Exception { 21 | client.disconnect(); 22 | } 23 | 24 | @Test(expected = JedisConnectionException.class) 25 | public void checkUnkownHost() { 26 | client.setHost("someunknownhost"); 27 | client.connect(); 28 | } 29 | 30 | @Test(expected = JedisConnectionException.class) 31 | public void checkWrongPort() { 32 | client.setHost("localhost"); 33 | client.setPort(55665); 34 | client.connect(); 35 | } 36 | 37 | @Test 38 | public void connectIfNotConnectedWhenSettingTimeoutInfinite() { 39 | client.setHost("localhost"); 40 | client.setPort(6379); 41 | client.setTimeoutInfinite(); 42 | } 43 | 44 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/benchmark/ShardedBenchmark.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.benchmark; 2 | 3 | import java.io.IOException; 4 | import java.net.UnknownHostException; 5 | import java.util.Calendar; 6 | 7 | import redis.clients.util.Hashing; 8 | 9 | public class ShardedBenchmark { 10 | private static final int TOTAL_OPERATIONS = 10000000; 11 | 12 | public static void main(String[] args) throws UnknownHostException, 13 | IOException { 14 | 15 | long begin = Calendar.getInstance().getTimeInMillis(); 16 | 17 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 18 | String key = "foo" + n; 19 | Hashing.MD5.hash(key); 20 | } 21 | 22 | long elapsed = Calendar.getInstance().getTimeInMillis() - begin; 23 | 24 | System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) + " MD5 ops"); 25 | 26 | begin = Calendar.getInstance().getTimeInMillis(); 27 | 28 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 29 | String key = "foo" + n; 30 | Hashing.MURMUR_HASH.hash(key); 31 | } 32 | 33 | elapsed = Calendar.getInstance().getTimeInMillis() - begin; 34 | 35 | System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) 36 | + " Murmur ops"); 37 | 38 | } 39 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/benchmark/SafeEncoderBenchmark.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.benchmark; 2 | 3 | import java.io.IOException; 4 | import java.net.UnknownHostException; 5 | import java.util.Calendar; 6 | 7 | import redis.clients.util.SafeEncoder; 8 | 9 | public class SafeEncoderBenchmark { 10 | private static final int TOTAL_OPERATIONS = 10000000; 11 | 12 | public static void main(String[] args) throws UnknownHostException, 13 | IOException { 14 | long begin = Calendar.getInstance().getTimeInMillis(); 15 | 16 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 17 | SafeEncoder.encode("foo bar!"); 18 | } 19 | 20 | long elapsed = Calendar.getInstance().getTimeInMillis() - begin; 21 | 22 | System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) 23 | + " ops to build byte[]"); 24 | 25 | begin = Calendar.getInstance().getTimeInMillis(); 26 | 27 | byte[] bytes = "foo bar!".getBytes(); 28 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 29 | SafeEncoder.encode(bytes); 30 | } 31 | 32 | elapsed = Calendar.getInstance().getTimeInMillis() - begin; 33 | 34 | System.out.println(((1000 * TOTAL_OPERATIONS) / elapsed) 35 | + " ops to build Strings"); 36 | 37 | } 38 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/Hashing.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | import java.security.MessageDigest; 4 | import java.security.NoSuchAlgorithmException; 5 | 6 | public interface Hashing { 7 | public static final Hashing MURMUR_HASH = new MurmurHash(); 8 | public ThreadLocal md5Holder = new ThreadLocal(); 9 | 10 | public static final Hashing MD5 = new Hashing() { 11 | public long hash(String key) { 12 | return hash(SafeEncoder.encode(key)); 13 | } 14 | 15 | public long hash(byte[] key) { 16 | try { 17 | if (md5Holder.get() == null) { 18 | md5Holder.set(MessageDigest.getInstance("MD5")); 19 | } 20 | } catch (NoSuchAlgorithmException e) { 21 | throw new IllegalStateException("++++ no md5 algorythm found"); 22 | } 23 | MessageDigest md5 = md5Holder.get(); 24 | 25 | md5.reset(); 26 | md5.update(key); 27 | byte[] bKey = md5.digest(); 28 | long res = ((long) (bKey[3] & 0xFF) << 24) 29 | | ((long) (bKey[2] & 0xFF) << 16) 30 | | ((long) (bKey[1] & 0xFF) << 8) | (long) (bKey[0] & 0xFF); 31 | return res; 32 | } 33 | }; 34 | 35 | public long hash(String key); 36 | 37 | public long hash(byte[] key); 38 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/SafeEncoder.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | import java.io.UnsupportedEncodingException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import redis.clients.jedis.Protocol; 8 | import redis.clients.jedis.exceptions.JedisDataException; 9 | import redis.clients.jedis.exceptions.JedisException; 10 | 11 | /** 12 | * The only reason to have this is to be able to compatible with java 1.5 :( 13 | * 14 | */ 15 | public class SafeEncoder { 16 | public static byte[][] encodeMany(final String... strs){ 17 | byte[][] many = new byte[strs.length][]; 18 | for(int i=0;i args; 11 | 12 | @SuppressWarnings("unchecked") 13 | public static List from(List nestedMultiBulkReply){ 14 | List logs = new ArrayList(nestedMultiBulkReply.size()); 15 | for(Object obj : nestedMultiBulkReply){ 16 | List properties = (List)obj; 17 | logs.add(new Slowlog(properties)); 18 | } 19 | 20 | return logs; 21 | } 22 | 23 | @SuppressWarnings("unchecked") 24 | private Slowlog(List properties) { 25 | super(); 26 | this.id = (Long)properties.get(0); 27 | this.timeStamp = (Long)properties.get(1); 28 | this.executionTime = (Long)properties.get(2); 29 | 30 | List bargs = (List)properties.get(3); 31 | this.args = new ArrayList(bargs.size()); 32 | 33 | for(byte[] barg:bargs){ 34 | this.args.add(SafeEncoder.encode(barg)); 35 | } 36 | } 37 | 38 | public long getId() { 39 | return id; 40 | } 41 | 42 | public long getTimeStamp() { 43 | return timeStamp; 44 | } 45 | 46 | public long getExecutionTime() { 47 | return executionTime; 48 | } 49 | 50 | public List getArgs() { 51 | return args; 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/ObjectCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import org.junit.Test; 4 | 5 | import redis.clients.util.SafeEncoder; 6 | 7 | public class ObjectCommandsTest extends JedisCommandTestBase { 8 | 9 | private String key = "mylist"; 10 | private byte[] binaryKey = SafeEncoder.encode(key); 11 | 12 | @Test 13 | public void objectRefcount() { 14 | jedis.lpush(key, "hello world"); 15 | Long refcount = jedis.objectRefcount(key); 16 | assertEquals(new Long(1), refcount); 17 | 18 | // Binary 19 | refcount = jedis.objectRefcount(binaryKey); 20 | assertEquals(new Long(1), refcount); 21 | 22 | } 23 | 24 | @Test 25 | public void objectEncoding() { 26 | jedis.lpush(key, "hello world"); 27 | String encoding = jedis.objectEncoding(key); 28 | assertEquals("ziplist", encoding); 29 | 30 | // Binary 31 | encoding = SafeEncoder.encode(jedis.objectEncoding(binaryKey)); 32 | assertEquals("ziplist", encoding); 33 | } 34 | 35 | @Test 36 | public void objectIdletime() throws InterruptedException { 37 | jedis.lpush(key, "hello world"); 38 | 39 | // Wait a little bit more than 10 seconds so the idle time is 10 40 | // seconds. 41 | Thread.sleep(10001); 42 | Long time = jedis.objectIdletime(key); 43 | assertEquals(new Long(10), time); 44 | 45 | // Binary 46 | time = jedis.objectIdletime(binaryKey); 47 | assertEquals(new Long(10), time); 48 | } 49 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/SlowlogCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.Test; 6 | 7 | import redis.clients.util.Slowlog; 8 | 9 | public class SlowlogCommandsTest extends JedisCommandTestBase { 10 | 11 | @Test 12 | public void slowlog() { 13 | //do something 14 | jedis.configSet("slowlog-log-slower-than", "0"); 15 | jedis.set("foo", "bar"); 16 | jedis.set("foo2", "bar2"); 17 | 18 | List reducedLog = jedis.slowlogGet(1); 19 | assertEquals(1, reducedLog.size()); 20 | 21 | Slowlog log = reducedLog.get(0); 22 | assertTrue(log.getId() > 0); 23 | assertTrue(log.getTimeStamp() > 0); 24 | assertTrue(log.getExecutionTime() > 0); 25 | assertNotNull(log.getArgs()); 26 | 27 | List breducedLog = jedis.slowlogGetBinary(1); 28 | assertEquals(1, breducedLog.size()); 29 | 30 | List log1 = jedis.slowlogGet(); 31 | List blog1 = jedis.slowlogGetBinary(); 32 | 33 | assertNotNull(log1); 34 | assertNotNull(blog1); 35 | 36 | long len1 = jedis.slowlogLen(); 37 | 38 | jedis.slowlogReset(); 39 | 40 | List log2 = jedis.slowlogGet(); 41 | List blog2 = jedis.slowlogGetBinary(); 42 | long len2 = jedis.slowlogLen(); 43 | 44 | assertTrue(len1 > len2); 45 | assertTrue(log1.size() > log2.size()); 46 | assertTrue(blog1.size() > blog2.size()); 47 | } 48 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/benchmark/HashingBenchmark.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.benchmark; 2 | 3 | import java.io.IOException; 4 | import java.net.UnknownHostException; 5 | import java.util.ArrayList; 6 | import java.util.Calendar; 7 | import java.util.Collection; 8 | import java.util.List; 9 | 10 | import redis.clients.jedis.Jedis; 11 | import redis.clients.jedis.JedisShardInfo; 12 | import redis.clients.jedis.ShardedJedis; 13 | import redis.clients.jedis.tests.HostAndPortUtil; 14 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 15 | 16 | public class HashingBenchmark { 17 | private static HostAndPort hnp1 = HostAndPortUtil.getRedisServers().get(0); 18 | private static HostAndPort hnp2 = HostAndPortUtil.getRedisServers().get(1); 19 | private static final int TOTAL_OPERATIONS = 100000; 20 | 21 | public static void main(String[] args) throws UnknownHostException, 22 | IOException { 23 | List shards = new ArrayList(); 24 | JedisShardInfo shard = new JedisShardInfo(hnp1.host, hnp1.port); 25 | shard.setPassword("foobared"); 26 | shards.add(shard); 27 | shard = new JedisShardInfo(hnp2.host, hnp2.port); 28 | shard.setPassword("foobared"); 29 | shards.add(shard); 30 | ShardedJedis jedis = new ShardedJedis(shards); 31 | Collection allShards = jedis.getAllShards(); 32 | for (Jedis j : allShards) { 33 | j.flushAll(); 34 | } 35 | 36 | long begin = Calendar.getInstance().getTimeInMillis(); 37 | 38 | for (int n = 0; n <= TOTAL_OPERATIONS; n++) { 39 | String key = "foo" + n; 40 | jedis.set(key, "bar" + n); 41 | jedis.get(key); 42 | } 43 | 44 | long elapsed = Calendar.getInstance().getTimeInMillis() - begin; 45 | 46 | jedis.disconnect(); 47 | 48 | System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops"); 49 | } 50 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/MultiKeyCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public interface MultiKeyCommands { 8 | Long del(String... keys); 9 | 10 | List blpop(int timeout, String... keys); 11 | 12 | List brpop(int timeout, String... keys); 13 | 14 | List blpop(String... args); 15 | 16 | List brpop(String... args); 17 | 18 | Set keys(String pattern); 19 | 20 | List mget(String... keys); 21 | 22 | String mset(String... keysvalues); 23 | 24 | Long msetnx(String... keysvalues); 25 | 26 | String rename(String oldkey, String newkey); 27 | 28 | Long renamenx(String oldkey, String newkey); 29 | 30 | String rpoplpush(String srckey, String dstkey); 31 | 32 | Set sdiff(String... keys); 33 | 34 | Long sdiffstore(String dstkey, String... keys); 35 | 36 | Set sinter(String... keys); 37 | 38 | Long sinterstore(String dstkey, String... keys); 39 | 40 | Long smove(String srckey, String dstkey, String member); 41 | 42 | Long sort(String key, SortingParams sortingParameters, String dstkey); 43 | 44 | Long sort(String key, String dstkey); 45 | 46 | Set sunion(String... keys); 47 | 48 | Long sunionstore(String dstkey, String... keys); 49 | 50 | String watch(String... keys); 51 | 52 | String unwatch(); 53 | 54 | Long zinterstore(String dstkey, String... sets); 55 | 56 | Long zinterstore(String dstkey, ZParams params, String... sets); 57 | 58 | Long zunionstore(String dstkey, String... sets); 59 | 60 | Long zunionstore(String dstkey, ZParams params, String... sets); 61 | 62 | String brpoplpush(String source, String destination, int timeout); 63 | 64 | Long publish(String channel, String message); 65 | 66 | void subscribe(JedisPubSub jedisPubSub, String... channels); 67 | 68 | void psubscribe(JedisPubSub jedisPubSub, String... patterns); 69 | 70 | String randomKey(); 71 | 72 | Long bitop(BitOP op, final String destKey, String... srcKeys); 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/MultiKeyBinaryCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | public interface MultiKeyBinaryCommands { 8 | Long del(byte[]... keys); 9 | 10 | List blpop(int timeout, byte[]... keys); 11 | 12 | List brpop(int timeout, byte[]... keys); 13 | 14 | List blpop(byte[]... args); 15 | 16 | List brpop(byte[]... args); 17 | 18 | Set keys(byte[] pattern); 19 | 20 | List mget(byte[]... keys); 21 | 22 | String mset(byte[]... keysvalues); 23 | 24 | Long msetnx(byte[]... keysvalues); 25 | 26 | String rename(byte[] oldkey, byte[] newkey); 27 | 28 | Long renamenx(byte[] oldkey, byte[] newkey); 29 | 30 | byte[] rpoplpush(byte[] srckey, byte[] dstkey); 31 | 32 | Set sdiff(byte[]... keys); 33 | 34 | Long sdiffstore(byte[] dstkey, byte[]... keys); 35 | 36 | Set sinter(byte[]... keys); 37 | 38 | Long sinterstore(byte[] dstkey, byte[]... keys); 39 | 40 | Long smove(byte[] srckey, byte[] dstkey, byte[] member); 41 | 42 | Long sort(byte[] key, SortingParams sortingParameters, byte[] dstkey); 43 | 44 | Long sort(byte[] key, byte[] dstkey); 45 | 46 | Set sunion(byte[]... keys); 47 | 48 | Long sunionstore(byte[] dstkey, byte[]... keys); 49 | 50 | String watch(byte[]... keys); 51 | 52 | String unwatch(); 53 | 54 | Long zinterstore(byte[] dstkey, byte[]... sets); 55 | 56 | Long zinterstore(byte[] dstkey, ZParams params, byte[]... sets); 57 | 58 | Long zunionstore(byte[] dstkey, byte[]... sets); 59 | 60 | Long zunionstore(byte[] dstkey, ZParams params, byte[]... sets); 61 | 62 | byte[] brpoplpush(byte[] source, byte[] destination, int timeout); 63 | 64 | Long publish(byte[] channel, byte[] message); 65 | 66 | void subscribe(BinaryJedisPubSub jedisPubSub, byte[]... channels); 67 | 68 | void psubscribe(BinaryJedisPubSub jedisPubSub, byte[]... patterns); 69 | 70 | byte[] randomBinaryKey(); 71 | 72 | Long bitop(BitOP op, final byte[] destKey, byte[]... srcKeys); 73 | } 74 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/Pool.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | import org.apache.commons.pool.PoolableObjectFactory; 4 | import org.apache.commons.pool.impl.GenericObjectPool; 5 | 6 | import redis.clients.jedis.exceptions.JedisConnectionException; 7 | import redis.clients.jedis.exceptions.JedisException; 8 | 9 | public abstract class Pool { 10 | protected GenericObjectPool internalPool; 11 | 12 | protected Pool() { 13 | this.internalPool = null; 14 | } 15 | 16 | public Pool(final GenericObjectPool.Config poolConfig, 17 | PoolableObjectFactory factory) { 18 | this.internalPool = new GenericObjectPool(factory, poolConfig); 19 | } 20 | 21 | @SuppressWarnings("unchecked") 22 | public T getResource() { 23 | try { 24 | return (T) internalPool.borrowObject(); 25 | } catch (Exception e) { 26 | throw new JedisConnectionException( 27 | "Could not get a resource from the pool", e); 28 | } 29 | } 30 | 31 | public void returnResourceObject(final Object resource) { 32 | try { 33 | internalPool.returnObject(resource); 34 | } catch (Exception e) { 35 | throw new JedisException( 36 | "Could not return the resource to the pool", e); 37 | } 38 | } 39 | 40 | public void returnBrokenResource(final T resource) { 41 | returnBrokenResourceObject(resource); 42 | } 43 | 44 | public void returnResource(final T resource) { 45 | returnResourceObject(resource); 46 | } 47 | 48 | protected void returnBrokenResourceObject(final Object resource) { 49 | try { 50 | internalPool.invalidateObject(resource); 51 | } catch (Exception e) { 52 | throw new JedisException( 53 | "Could not return the resource to the pool", e); 54 | } 55 | } 56 | 57 | public void destroy() { 58 | try { 59 | internalPool.close(); 60 | } catch (Exception e) { 61 | throw new JedisException("Could not destroy the pool", e); 62 | } 63 | } 64 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/MultiKeyCommandsPipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | 8 | /** 9 | * Multikey related commands (these are split out because they are non-shardable) 10 | */ 11 | public interface MultiKeyCommandsPipeline { 12 | Response del(String... keys); 13 | 14 | Response> blpop(String... args); 15 | 16 | Response> brpop(String... args); 17 | 18 | Response> keys(String pattern); 19 | 20 | Response> mget(String... keys); 21 | 22 | Response mset(String... keysvalues); 23 | 24 | Response msetnx(String... keysvalues); 25 | 26 | Response rename(String oldkey, String newkey); 27 | 28 | Response renamenx(String oldkey, String newkey); 29 | 30 | Response rpoplpush(String srckey, String dstkey); 31 | 32 | Response> sdiff(String... keys); 33 | 34 | Response sdiffstore(String dstkey, String... keys); 35 | 36 | Response> sinter(String... keys); 37 | 38 | Response sinterstore(String dstkey, String... keys); 39 | 40 | Response smove(String srckey, String dstkey, String member); 41 | 42 | Response> sort(String key, SortingParams sortingParameters, String dstkey); 43 | 44 | Response> sort(String key, String dstkey); 45 | 46 | Response> sunion(String... keys); 47 | 48 | Response sunionstore(String dstkey, String... keys); 49 | 50 | Response watch(String... keys); 51 | 52 | Response zinterstore(String dstkey, String... sets); 53 | 54 | Response zinterstore(String dstkey, ZParams params, String... sets); 55 | 56 | Response zunionstore(String dstkey, String... sets); 57 | 58 | Response zunionstore(String dstkey, ZParams params, String... sets); 59 | 60 | Response brpoplpush(String source, String destination, int timeout); 61 | 62 | Response publish(String channel, String message); 63 | 64 | Response randomKey(); 65 | 66 | Response bitop(BitOP op, final String destKey, String... srcKeys); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/MultiKeyBinaryRedisPipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | 4 | import java.util.List; 5 | import java.util.Set; 6 | 7 | /** 8 | * Multikey related commands (these are split out because they are non-shardable) 9 | */ 10 | public interface MultiKeyBinaryRedisPipeline { 11 | 12 | Response del(byte[]... keys); 13 | 14 | Response> blpop(byte[]... args); 15 | 16 | Response> brpop(byte[]... args); 17 | 18 | Response> keys(byte[] pattern); 19 | 20 | Response> mget(byte[]... keys); 21 | 22 | Response mset(byte[]... keysvalues); 23 | 24 | Response msetnx(byte[]... keysvalues); 25 | 26 | Response rename(byte[] oldkey, byte[] newkey); 27 | 28 | Response renamenx(byte[] oldkey, byte[] newkey); 29 | 30 | Response rpoplpush(byte[] srckey, byte[] dstkey); 31 | 32 | Response> sdiff(byte[]... keys); 33 | 34 | Response sdiffstore(byte[] dstkey, byte[]... keys); 35 | 36 | Response> sinter(byte[]... keys); 37 | 38 | Response sinterstore(byte[] dstkey, byte[]... keys); 39 | 40 | Response smove(byte[] srckey, byte[] dstkey, byte[] member); 41 | 42 | Response> sort(byte[] key, SortingParams sortingParameters, byte[] dstkey); 43 | 44 | Response> sort(byte[] key, byte[] dstkey); 45 | 46 | Response> sunion(byte[]... keys); 47 | 48 | Response sunionstore(byte[] dstkey, byte[]... keys); 49 | 50 | Response watch(byte[]... keys); 51 | 52 | Response zinterstore(byte[] dstkey, byte[]... sets); 53 | 54 | Response zinterstore(byte[] dstkey, ZParams params, byte[]... sets); 55 | 56 | Response zunionstore(byte[] dstkey, byte[]... sets); 57 | 58 | Response zunionstore(byte[] dstkey, ZParams params, byte[]... sets); 59 | 60 | Response brpoplpush(byte[] source, byte[] destination, int timeout); 61 | 62 | Response publish(byte[] channel, byte[] message); 63 | 64 | Response randomKeyBinary(); 65 | 66 | Response bitop(BitOP op, final byte[] destKey, byte[]... srcKeys); 67 | } 68 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Transaction.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import redis.clients.jedis.exceptions.JedisDataException; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | /** 9 | * Transaction is nearly identical to Pipeline, only differences are the multi/discard behaviors 10 | */ 11 | public class Transaction extends MultiKeyPipelineBase { 12 | 13 | protected boolean inTransaction = true; 14 | 15 | protected Transaction(){ 16 | // client will be set later in transaction block 17 | } 18 | 19 | public Transaction(final Client client) { 20 | this.client = client; 21 | } 22 | 23 | @Override 24 | protected Client getClient(String key) { 25 | return client; 26 | } 27 | 28 | @Override 29 | protected Client getClient(byte[] key) { 30 | return client; 31 | } 32 | 33 | public List exec() { 34 | client.exec(); 35 | client.getAll(1); // Discard all but the last reply 36 | 37 | List unformatted = client.getObjectMultiBulkReply(); 38 | if (unformatted == null) { 39 | return null; 40 | } 41 | List formatted = new ArrayList(); 42 | for (Object o : unformatted) { 43 | try { 44 | formatted.add(generateResponse(o).get()); 45 | } catch (JedisDataException e) { 46 | formatted.add(e); 47 | } 48 | } 49 | return formatted; 50 | } 51 | 52 | public List> execGetResponse() { 53 | client.exec(); 54 | client.getAll(1); // Discard all but the last reply 55 | 56 | List unformatted = client.getObjectMultiBulkReply(); 57 | if (unformatted == null) { 58 | return null; 59 | } 60 | List> response = new ArrayList>(); 61 | for (Object o : unformatted) { 62 | response.add(generateResponse(o)); 63 | } 64 | return response; 65 | } 66 | 67 | public String discard() { 68 | client.discard(); 69 | client.getAll(1); // Discard all but the last reply 70 | inTransaction = false; 71 | clean(); 72 | return client.getStatusCodeReply(); 73 | } 74 | 75 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Tuple.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.Arrays; 4 | 5 | import redis.clients.util.SafeEncoder; 6 | 7 | public class Tuple implements Comparable { 8 | private byte[] element; 9 | private Double score; 10 | 11 | public int hashCode() { 12 | final int prime = 31; 13 | int result = 1; 14 | result = prime * result; 15 | if (null != element) { 16 | for (final byte b : element) { 17 | result = prime * result + b; 18 | } 19 | } 20 | long temp; 21 | temp = Double.doubleToLongBits(score); 22 | result = prime * result + (int) (temp ^ (temp >>> 32)); 23 | return result; 24 | } 25 | 26 | public boolean equals(Object obj) { 27 | if (this == obj) 28 | return true; 29 | if (obj == null) 30 | return false; 31 | if (getClass() != obj.getClass()) 32 | return false; 33 | Tuple other = (Tuple) obj; 34 | if (element == null) { 35 | if (other.element != null) 36 | return false; 37 | } else if (!Arrays.equals(element, other.element)) 38 | return false; 39 | return true; 40 | } 41 | 42 | public int compareTo(Tuple other) { 43 | if (Arrays.equals(this.element, other.element)) 44 | return 0; 45 | else 46 | return this.score < other.getScore() ? -1 : 1; 47 | } 48 | 49 | public Tuple(String element, Double score) { 50 | super(); 51 | this.element = SafeEncoder.encode(element); 52 | this.score = score; 53 | } 54 | 55 | public Tuple(byte[] element, Double score) { 56 | super(); 57 | this.element = element; 58 | this.score = score; 59 | } 60 | 61 | public String getElement() { 62 | if (null != element) { 63 | return SafeEncoder.encode(element); 64 | } else { 65 | return null; 66 | } 67 | } 68 | 69 | public byte[] getBinaryElement() { 70 | return element; 71 | } 72 | 73 | public double getScore() { 74 | return score; 75 | } 76 | 77 | public String toString() { 78 | return '[' + Arrays.toString(element) + ',' + score + ']'; 79 | } 80 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/benchmark/PoolBenchmark.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.benchmark; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | import java.util.concurrent.atomic.AtomicInteger; 6 | 7 | import org.apache.commons.pool.impl.GenericObjectPool.Config; 8 | 9 | import redis.clients.jedis.Jedis; 10 | import redis.clients.jedis.JedisPool; 11 | import redis.clients.jedis.tests.HostAndPortUtil; 12 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 13 | 14 | public class PoolBenchmark { 15 | private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); 16 | private static final int TOTAL_OPERATIONS = 100000; 17 | 18 | public static void main(String[] args) throws Exception { 19 | Jedis j = new Jedis(hnp.host, hnp.port); 20 | j.connect(); 21 | j.auth("foobared"); 22 | j.flushAll(); 23 | j.quit(); 24 | j.disconnect(); 25 | long t = System.currentTimeMillis(); 26 | // withoutPool(); 27 | withPool(); 28 | long elapsed = System.currentTimeMillis() - t; 29 | System.out.println(((1000 * 2 * TOTAL_OPERATIONS) / elapsed) + " ops"); 30 | } 31 | 32 | private static void withPool() throws Exception { 33 | final JedisPool pool = new JedisPool(new Config(), hnp.host, hnp.port, 34 | 2000, "foobared"); 35 | List tds = new ArrayList(); 36 | 37 | final AtomicInteger ind = new AtomicInteger(); 38 | for (int i = 0; i < 50; i++) { 39 | Thread hj = new Thread(new Runnable() { 40 | public void run() { 41 | for (int i = 0; (i = ind.getAndIncrement()) < TOTAL_OPERATIONS;) { 42 | try { 43 | Jedis j = pool.getResource(); 44 | final String key = "foo" + i; 45 | j.set(key, key); 46 | j.get(key); 47 | pool.returnResource(j); 48 | } catch (Exception e) { 49 | e.printStackTrace(); 50 | } 51 | } 52 | } 53 | }); 54 | tds.add(hj); 55 | hj.start(); 56 | } 57 | 58 | for (Thread t : tds) 59 | t.join(); 60 | 61 | pool.destroy(); 62 | } 63 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/JedisSentinelTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import static junit.framework.Assert.assertEquals; 4 | import static junit.framework.Assert.assertFalse; 5 | import static junit.framework.Assert.assertTrue; 6 | 7 | import java.util.List; 8 | import java.util.Map; 9 | 10 | import org.junit.After; 11 | import org.junit.Before; 12 | import org.junit.Test; 13 | 14 | import redis.clients.jedis.Jedis; 15 | 16 | public class JedisSentinelTest { 17 | private static final String MASTER_NAME = "mymaster"; 18 | 19 | @Before 20 | public void setup() throws InterruptedException { 21 | Jedis j = new Jedis("localhost", 6380); 22 | j.auth("foobared"); 23 | j.configSet("masterauth", "foobared"); 24 | j.slaveof("localhost", 6379); 25 | // TODO: The sleep is to give time to the slave to synchronize with the 26 | // master and also let know the sentinels about this new topology. We 27 | // should find a better way to do this. 28 | Thread.sleep(5000); 29 | } 30 | 31 | @After 32 | public void clear() { 33 | Jedis j = new Jedis("localhost", 6380); 34 | j.auth("foobared"); 35 | j.slaveofNoOne(); 36 | } 37 | 38 | @Test 39 | public void sentinel() { 40 | Jedis j = new Jedis("localhost", 26379); 41 | List> masters = j.sentinelMasters(); 42 | final String masterName = masters.get(0).get("name"); 43 | 44 | assertEquals(MASTER_NAME, masterName); 45 | 46 | List masterHostAndPort = j 47 | .sentinelGetMasterAddrByName(masterName); 48 | assertEquals("127.0.0.1", masterHostAndPort.get(0)); 49 | assertEquals("6379", masterHostAndPort.get(1)); 50 | 51 | List> slaves = j.sentinelSlaves(masterName); 52 | assertEquals("6379", slaves.get(0).get("master-port")); 53 | 54 | List isMasterDownByAddr = j 55 | .sentinelIsMasterDownByAddr("127.0.0.1", 6379); 56 | assertEquals(Long.valueOf(0), (Long) isMasterDownByAddr.get(0)); 57 | assertFalse("?".equals(isMasterDownByAddr.get(1))); 58 | 59 | isMasterDownByAddr = j.sentinelIsMasterDownByAddr("127.0.0.1", 1); 60 | assertEquals(Long.valueOf(0), (Long) isMasterDownByAddr.get(0)); 61 | assertTrue("?".equals(isMasterDownByAddr.get(1))); 62 | 63 | // DO NOT RE-RUN TEST TOO FAST, RESET TAKES SOME TIME TO... RESET 64 | assertEquals(Long.valueOf(1), j.sentinelReset(masterName)); 65 | assertEquals(Long.valueOf(0), j.sentinelReset("woof" + masterName)); 66 | 67 | } 68 | } 69 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/HostAndPortUtil.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import redis.clients.jedis.Protocol; 7 | 8 | public class HostAndPortUtil { 9 | private static List hostAndPortList = new ArrayList( 10 | 2); 11 | 12 | static { 13 | final HostAndPort defaulthnp1 = new HostAndPort(); 14 | defaulthnp1.host = "localhost"; 15 | defaulthnp1.port = Protocol.DEFAULT_PORT; 16 | hostAndPortList.add(defaulthnp1); 17 | 18 | final HostAndPort defaulthnp2 = new HostAndPort(); 19 | defaulthnp2.host = "localhost"; 20 | defaulthnp2.port = Protocol.DEFAULT_PORT + 1; 21 | hostAndPortList.add(defaulthnp2); 22 | 23 | final String envHosts = System.getProperty("redis-hosts"); 24 | if (null != envHosts && 0 < envHosts.length()) { 25 | final String[] hostDefs = envHosts.split(","); 26 | if (null != hostDefs && 2 <= hostDefs.length) { 27 | hostAndPortList = new ArrayList( 28 | hostDefs.length); 29 | for (String hostDef : hostDefs) { 30 | final String[] hostAndPort = hostDef.split(":"); 31 | if (null != hostAndPort && 2 == hostAndPort.length) { 32 | final HostAndPort hnp = new HostAndPort(); 33 | hnp.host = hostAndPort[0]; 34 | try { 35 | hnp.port = Integer.parseInt(hostAndPort[1]); 36 | } catch (final NumberFormatException nfe) { 37 | hnp.port = Protocol.DEFAULT_PORT; 38 | } 39 | hostAndPortList.add(hnp); 40 | } 41 | } 42 | } 43 | } 44 | final StringBuilder strb = new StringBuilder( 45 | "Redis hosts to be used : "); 46 | for (HostAndPort hnp : hostAndPortList) { 47 | strb.append('[').append(hnp.host).append(':').append(hnp.port) 48 | .append(']').append(' '); 49 | } 50 | System.out.println(strb); 51 | } 52 | 53 | public static List getRedisServers() { 54 | return hostAndPortList; 55 | } 56 | 57 | public static class HostAndPort { 58 | public String host; 59 | public int port; 60 | } 61 | } 62 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisShardInfo.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.net.URI; 4 | 5 | import redis.clients.util.ShardInfo; 6 | import redis.clients.util.Sharded; 7 | 8 | public class JedisShardInfo extends ShardInfo { 9 | public String toString() { 10 | return host + ":" + port + "*" + getWeight(); 11 | } 12 | 13 | private int timeout; 14 | private String host; 15 | private int port; 16 | private String password = null; 17 | private String name = null; 18 | 19 | public String getHost() { 20 | return host; 21 | } 22 | 23 | public int getPort() { 24 | return port; 25 | } 26 | 27 | public JedisShardInfo(String host) { 28 | super(Sharded.DEFAULT_WEIGHT); 29 | URI uri = URI.create(host); 30 | if (uri.getScheme() != null && uri.getScheme().equals("redis")) { 31 | this.host = uri.getHost(); 32 | this.port = uri.getPort(); 33 | this.password = uri.getUserInfo().split(":", 2)[1]; 34 | } else { 35 | this.host = host; 36 | this.port = Protocol.DEFAULT_PORT; 37 | } 38 | } 39 | 40 | public JedisShardInfo(String host, String name) { 41 | this(host, Protocol.DEFAULT_PORT, name); 42 | } 43 | 44 | public JedisShardInfo(String host, int port) { 45 | this(host, port, 2000); 46 | } 47 | 48 | public JedisShardInfo(String host, int port, String name) { 49 | this(host, port, 2000, name); 50 | } 51 | 52 | public JedisShardInfo(String host, int port, int timeout) { 53 | this(host, port, timeout, Sharded.DEFAULT_WEIGHT); 54 | } 55 | 56 | public JedisShardInfo(String host, int port, int timeout, String name) { 57 | this(host, port, timeout, Sharded.DEFAULT_WEIGHT); 58 | this.name = name; 59 | } 60 | 61 | public JedisShardInfo(String host, int port, int timeout, int weight) { 62 | super(weight); 63 | this.host = host; 64 | this.port = port; 65 | this.timeout = timeout; 66 | } 67 | 68 | public JedisShardInfo(URI uri) { 69 | super(Sharded.DEFAULT_WEIGHT); 70 | this.host = uri.getHost(); 71 | this.port = uri.getPort(); 72 | this.password = uri.getUserInfo().split(":", 2)[1]; 73 | } 74 | 75 | public String getPassword() { 76 | return password; 77 | } 78 | 79 | public void setPassword(String auth) { 80 | this.password = auth; 81 | } 82 | 83 | public int getTimeout() { 84 | return timeout; 85 | } 86 | 87 | public void setTimeout(int timeout) { 88 | this.timeout = timeout; 89 | } 90 | 91 | public String getName() { 92 | return name; 93 | } 94 | 95 | @Override 96 | public Jedis createResource() { 97 | return new Jedis(this); 98 | } 99 | } 100 | -------------------------------------------------------------------------------- /gradlew.bat: -------------------------------------------------------------------------------- 1 | @if "%DEBUG%" == "" @echo off 2 | @rem ########################################################################## 3 | @rem ## 4 | @rem Gradle startup script for Windows ## 5 | @rem ## 6 | @rem ########################################################################## 7 | 8 | @rem Set local scope for the variables with windows NT shell 9 | if "%OS%"=="Windows_NT" setlocal 10 | 11 | @rem Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together. 12 | @rem set GRADLE_OPTS=%GRADLE_OPTS% -Xmx512m 13 | @rem set JAVA_OPTS=%JAVA_OPTS% -Xmx512m 14 | 15 | set DIRNAME=%~dp0 16 | if "%DIRNAME%" == "" set DIRNAME=.\ 17 | 18 | @rem Find java.exe 19 | set JAVA_EXE=java.exe 20 | if not defined JAVA_HOME goto init 21 | 22 | set JAVA_HOME=%JAVA_HOME:"=% 23 | set JAVA_EXE=%JAVA_HOME%/bin/java.exe 24 | 25 | if exist "%JAVA_EXE%" goto init 26 | 27 | echo. 28 | echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 29 | echo. 30 | echo Please set the JAVA_HOME variable in your environment to match the 31 | echo location of your Java installation. 32 | echo. 33 | goto end 34 | 35 | :init 36 | @rem Get command-line arguments, handling Windowz variants 37 | 38 | if not "%OS%" == "Windows_NT" goto win9xME_args 39 | if "%eval[2+2]" == "4" goto 4NT_args 40 | 41 | :win9xME_args 42 | @rem Slurp the command line arguments. 43 | set CMD_LINE_ARGS= 44 | set _SKIP=2 45 | 46 | :win9xME_args_slurp 47 | if "x%~1" == "x" goto execute 48 | 49 | set CMD_LINE_ARGS=%* 50 | goto execute 51 | 52 | :4NT_args 53 | @rem Get arguments from the 4NT Shell from JP Software 54 | set CMD_LINE_ARGS=%$ 55 | 56 | :execute 57 | @rem Setup the command line 58 | 59 | set STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain 60 | set CLASSPATH=%DIRNAME%\gradle\wrapper\gradle-wrapper.jar 61 | set WRAPPER_PROPERTIES=%DIRNAME%\gradle\wrapper\gradle-wrapper.properties 62 | 63 | set GRADLE_OPTS=%JAVA_OPTS% %GRADLE_OPTS% -Dorg.gradle.wrapper.properties="%WRAPPER_PROPERTIES%" 64 | 65 | @rem Execute Gradle 66 | "%JAVA_EXE%" %GRADLE_OPTS% -classpath "%CLASSPATH%" %STARTER_MAIN_CLASS% %CMD_LINE_ARGS% 67 | 68 | :end 69 | @rem End local scope for the variables with windows NT shell 70 | if "%ERRORLEVEL%"=="0" goto mainEnd 71 | 72 | if not "%OS%"=="Windows_NT" echo 1 > nul | choice /n /c:1 73 | 74 | rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of 75 | rem the _cmd.exe /c_ return code! 76 | if not "" == "%GRADLE_EXIT_CONSOLE%" exit "%ERRORLEVEL%" 77 | exit /b "%ERRORLEVEL%" 78 | 79 | :mainEnd 80 | if "%OS%"=="Windows_NT" endlocal 81 | 82 | :omega -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/BitCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import org.junit.Test; 4 | 5 | import redis.clients.jedis.BitOP; 6 | 7 | public class BitCommandsTest extends JedisCommandTestBase { 8 | @Test 9 | public void setAndgetbit() { 10 | boolean bit = jedis.setbit("foo", 0, true); 11 | assertEquals(false, bit); 12 | 13 | bit = jedis.getbit("foo", 0); 14 | assertEquals(true, bit); 15 | 16 | boolean bbit = jedis.setbit("bfoo".getBytes(), 0, "1".getBytes()); 17 | assertFalse(bbit); 18 | 19 | bbit = jedis.getbit("bfoo".getBytes(), 0); 20 | assertTrue(bbit); 21 | } 22 | 23 | @Test 24 | public void setAndgetrange() { 25 | jedis.set("key1", "Hello World"); 26 | long reply = jedis.setrange("key1", 6, "Jedis"); 27 | assertEquals(11, reply); 28 | 29 | assertEquals(jedis.get("key1"), "Hello Jedis"); 30 | 31 | assertEquals("Hello", jedis.getrange("key1", 0, 4)); 32 | assertEquals("Jedis", jedis.getrange("key1", 6, 11)); 33 | } 34 | 35 | @Test 36 | public void bitCount() { 37 | jedis.del("foo"); 38 | 39 | jedis.setbit("foo", 16, true); 40 | jedis.setbit("foo", 24, true); 41 | jedis.setbit("foo", 40, true); 42 | jedis.setbit("foo", 56, true); 43 | 44 | long c4 = jedis.bitcount("foo"); 45 | assertEquals(4, c4); 46 | 47 | long c3 = jedis.bitcount("foo", 2L, 5L); 48 | assertEquals(3, c3); 49 | 50 | jedis.del("foo"); 51 | } 52 | 53 | @Test 54 | public void bitOp() 55 | { 56 | jedis.set("key1", "\u0060"); 57 | jedis.set("key2", "\u0044"); 58 | 59 | jedis.bitop(BitOP.AND, "resultAnd", "key1", "key2"); 60 | String resultAnd = jedis.get("resultAnd"); 61 | assertEquals("\u0040", resultAnd); 62 | 63 | jedis.bitop(BitOP.OR, "resultOr", "key1", "key2"); 64 | String resultOr = jedis.get("resultOr"); 65 | assertEquals("\u0064", resultOr); 66 | 67 | jedis.bitop(BitOP.XOR, "resultXor", "key1", "key2"); 68 | String resultXor = jedis.get("resultXor"); 69 | assertEquals("\u0024", resultXor); 70 | 71 | jedis.del("resultAnd"); 72 | jedis.del("resultOr"); 73 | jedis.del("resultXor"); 74 | jedis.del("key1"); 75 | jedis.del("key2"); 76 | } 77 | 78 | @Test 79 | public void bitOpNot() 80 | { 81 | jedis.del("key"); 82 | jedis.setbit("key", 0, true); 83 | jedis.setbit("key", 4, true); 84 | 85 | jedis.bitop(BitOP.NOT, "resultNot", "key"); 86 | 87 | String resultNot = jedis.get("resultNot"); 88 | assertEquals("\u0077", resultNot); 89 | 90 | jedis.del("key"); 91 | jedis.del("resultNot"); 92 | } 93 | } 94 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/ShardedJedisPipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.ArrayList; 4 | import java.util.LinkedList; 5 | import java.util.List; 6 | import java.util.Queue; 7 | 8 | public class ShardedJedisPipeline extends PipelineBase { 9 | private BinaryShardedJedis jedis; 10 | private List results = new ArrayList(); 11 | private Queue clients = new LinkedList(); 12 | 13 | private static class FutureResult { 14 | private Client client; 15 | 16 | public FutureResult(Client client) { 17 | this.client = client; 18 | } 19 | 20 | public Object get() { 21 | return client.getOne(); 22 | } 23 | } 24 | 25 | public void setShardedJedis(BinaryShardedJedis jedis) { 26 | this.jedis = jedis; 27 | } 28 | 29 | public List getResults() { 30 | List r = new ArrayList(); 31 | for (FutureResult fr : results) { 32 | r.add(fr.get()); 33 | } 34 | return r; 35 | } 36 | 37 | /** 38 | * Syncronize pipeline by reading all responses. This operation closes the 39 | * pipeline. In order to get return values from pipelined commands, capture 40 | * the different Response<?> of the commands you execute. 41 | */ 42 | public void sync() { 43 | for (Client client : clients) { 44 | generateResponse(client.getOne()); 45 | } 46 | } 47 | 48 | /** 49 | * Syncronize pipeline by reading all responses. This operation closes the 50 | * pipeline. Whenever possible try to avoid using this version and use 51 | * ShardedJedisPipeline.sync() as it won't go through all the responses and generate the 52 | * right response type (usually it is a waste of time). 53 | * 54 | * @return A list of all the responses in the order you executed them. 55 | */ 56 | public List syncAndReturnAll() { 57 | List formatted = new ArrayList(); 58 | for (Client client : clients) { 59 | formatted.add(generateResponse(client.getOne()).get()); 60 | } 61 | return formatted; 62 | } 63 | 64 | /** 65 | * This method will be removed in Jedis 3.0. Use the methods that return Response's and call 66 | * sync(). 67 | */ 68 | @Deprecated 69 | public void execute() { 70 | } 71 | 72 | @Override 73 | protected Client getClient(String key) { 74 | Client client = jedis.getShard(key).getClient(); 75 | clients.add(client); 76 | results.add(new FutureResult(client)); 77 | return client; 78 | } 79 | 80 | @Override 81 | protected Client getClient(byte[] key) { 82 | Client client = jedis.getShard(key).getClient(); 83 | clients.add(client); 84 | results.add(new FutureResult(client)); 85 | return client; 86 | } 87 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/JedisCommandTestBase.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.Arrays; 4 | import java.util.Iterator; 5 | import java.util.List; 6 | import java.util.Set; 7 | 8 | import org.junit.After; 9 | import org.junit.Before; 10 | import org.junit.ComparisonFailure; 11 | 12 | import redis.clients.jedis.Jedis; 13 | import redis.clients.jedis.tests.HostAndPortUtil; 14 | import redis.clients.jedis.tests.JedisTestBase; 15 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 16 | 17 | public abstract class JedisCommandTestBase extends JedisTestBase { 18 | protected static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); 19 | 20 | protected Jedis jedis; 21 | 22 | public JedisCommandTestBase() { 23 | super(); 24 | } 25 | 26 | @Before 27 | public void setUp() throws Exception { 28 | jedis = new Jedis(hnp.host, hnp.port, 500); 29 | jedis.connect(); 30 | jedis.auth("foobared"); 31 | jedis.configSet("timeout", "300"); 32 | jedis.flushAll(); 33 | } 34 | 35 | @After 36 | public void tearDown() { 37 | jedis.disconnect(); 38 | } 39 | 40 | protected Jedis createJedis() { 41 | Jedis j = new Jedis(hnp.host, hnp.port); 42 | j.connect(); 43 | j.auth("foobared"); 44 | j.flushAll(); 45 | return j; 46 | } 47 | 48 | protected void assertEquals(List expected, List actual) { 49 | assertEquals(expected.size(), actual.size()); 50 | for (int n = 0; n < expected.size(); n++) { 51 | assertArrayEquals(expected.get(n), actual.get(n)); 52 | } 53 | } 54 | 55 | protected void assertEquals(Set expected, Set actual) { 56 | assertEquals(expected.size(), actual.size()); 57 | Iterator e = expected.iterator(); 58 | while (e.hasNext()) { 59 | byte[] next = e.next(); 60 | boolean contained = false; 61 | for (byte[] element : expected) { 62 | if (Arrays.equals(next, element)) { 63 | contained = true; 64 | } 65 | } 66 | if (!contained) { 67 | throw new ComparisonFailure("element is missing", 68 | Arrays.toString(next), actual.toString()); 69 | } 70 | } 71 | } 72 | 73 | protected boolean arrayContains(List array, byte[] expected) { 74 | for (byte[] a : array) { 75 | try { 76 | assertArrayEquals(a, expected); 77 | return true; 78 | } catch (AssertionError e) { 79 | 80 | } 81 | } 82 | return false; 83 | } 84 | 85 | protected boolean setContains(Set set, byte[] expected) { 86 | for (byte[] a : set) { 87 | try { 88 | assertArrayEquals(a, expected); 89 | return true; 90 | } catch (AssertionError e) { 91 | 92 | } 93 | } 94 | return false; 95 | } 96 | } 97 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/JedisTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.io.IOException; 4 | import java.net.URI; 5 | import java.net.URISyntaxException; 6 | import java.util.HashMap; 7 | import java.util.Map; 8 | 9 | import org.junit.Test; 10 | 11 | import redis.clients.jedis.Jedis; 12 | import redis.clients.jedis.JedisShardInfo; 13 | import redis.clients.jedis.Protocol; 14 | import redis.clients.jedis.exceptions.JedisConnectionException; 15 | import redis.clients.jedis.exceptions.JedisDataException; 16 | import redis.clients.jedis.tests.commands.JedisCommandTestBase; 17 | import redis.clients.util.SafeEncoder; 18 | 19 | public class JedisTest extends JedisCommandTestBase { 20 | @Test 21 | public void useWithoutConnecting() { 22 | Jedis jedis = new Jedis("localhost"); 23 | jedis.auth("foobared"); 24 | jedis.dbSize(); 25 | } 26 | 27 | @Test 28 | public void checkBinaryData() { 29 | byte[] bigdata = new byte[1777]; 30 | for (int b = 0; b < bigdata.length; b++) { 31 | bigdata[b] = (byte) ((byte) b % 255); 32 | } 33 | Map hash = new HashMap(); 34 | hash.put("data", SafeEncoder.encode(bigdata)); 35 | 36 | String status = jedis.hmset("foo", hash); 37 | assertEquals("OK", status); 38 | assertEquals(hash, jedis.hgetAll("foo")); 39 | } 40 | 41 | @Test 42 | public void connectWithShardInfo() { 43 | JedisShardInfo shardInfo = new JedisShardInfo("localhost", 44 | Protocol.DEFAULT_PORT); 45 | shardInfo.setPassword("foobared"); 46 | Jedis jedis = new Jedis(shardInfo); 47 | jedis.get("foo"); 48 | } 49 | 50 | @Test(expected = JedisConnectionException.class) 51 | public void timeoutConnection() throws Exception { 52 | jedis = new Jedis("localhost", 6379, 15000); 53 | jedis.auth("foobared"); 54 | jedis.configSet("timeout", "1"); 55 | // we need to sleep a long time since redis check for idle connections 56 | // every 10 seconds or so 57 | Thread.sleep(20000); 58 | jedis.hmget("foobar", "foo"); 59 | } 60 | 61 | @Test(expected = JedisDataException.class) 62 | public void failWhenSendingNullValues() { 63 | jedis.set("foo", null); 64 | } 65 | 66 | @Test 67 | public void shouldReconnectToSameDB() throws IOException { 68 | jedis.select(1); 69 | jedis.set("foo", "bar"); 70 | jedis.getClient().getSocket().shutdownInput(); 71 | jedis.getClient().getSocket().shutdownOutput(); 72 | assertEquals("bar", jedis.get("foo")); 73 | } 74 | 75 | @Test 76 | public void startWithUrlString() { 77 | Jedis j = new Jedis("localhost", 6380); 78 | j.auth("foobared"); 79 | j.select(2); 80 | j.set("foo", "bar"); 81 | Jedis jedis = new Jedis("redis://:foobared@localhost:6380/2"); 82 | assertEquals("PONG", jedis.ping()); 83 | assertEquals("bar", jedis.get("foo")); 84 | } 85 | 86 | @Test 87 | public void startWithUrl() throws URISyntaxException { 88 | Jedis j = new Jedis("localhost", 6380); 89 | j.auth("foobared"); 90 | j.select(2); 91 | j.set("foo", "bar"); 92 | Jedis jedis = new Jedis(new URI("redis://:foobared@localhost:6380/2")); 93 | assertEquals("PONG", jedis.ping()); 94 | assertEquals("bar", jedis.get("foo")); 95 | } 96 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/ShardedJedisPool.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.List; 4 | import java.util.regex.Pattern; 5 | 6 | import org.apache.commons.pool.BasePoolableObjectFactory; 7 | import org.apache.commons.pool.impl.GenericObjectPool; 8 | 9 | import redis.clients.util.Hashing; 10 | import redis.clients.util.Pool; 11 | 12 | public class ShardedJedisPool extends Pool { 13 | public ShardedJedisPool(final GenericObjectPool.Config poolConfig, 14 | List shards) { 15 | this(poolConfig, shards, Hashing.MURMUR_HASH); 16 | } 17 | 18 | public ShardedJedisPool(final GenericObjectPool.Config poolConfig, 19 | List shards, Hashing algo) { 20 | this(poolConfig, shards, algo, null); 21 | } 22 | 23 | public ShardedJedisPool(final GenericObjectPool.Config poolConfig, 24 | List shards, Pattern keyTagPattern) { 25 | this(poolConfig, shards, Hashing.MURMUR_HASH, keyTagPattern); 26 | } 27 | 28 | public ShardedJedisPool(final GenericObjectPool.Config poolConfig, 29 | List shards, Hashing algo, Pattern keyTagPattern) { 30 | super(poolConfig, new ShardedJedisFactory(shards, algo, keyTagPattern)); 31 | } 32 | 33 | /** 34 | * PoolableObjectFactory custom impl. 35 | */ 36 | private static class ShardedJedisFactory extends BasePoolableObjectFactory { 37 | private List shards; 38 | private Hashing algo; 39 | private Pattern keyTagPattern; 40 | 41 | public ShardedJedisFactory(List shards, Hashing algo, 42 | Pattern keyTagPattern) { 43 | this.shards = shards; 44 | this.algo = algo; 45 | this.keyTagPattern = keyTagPattern; 46 | } 47 | 48 | public Object makeObject() throws Exception { 49 | ShardedJedis jedis = new ShardedJedis(shards, algo, keyTagPattern); 50 | return jedis; 51 | } 52 | 53 | public void destroyObject(final Object obj) throws Exception { 54 | if ((obj != null) && (obj instanceof ShardedJedis)) { 55 | ShardedJedis shardedJedis = (ShardedJedis) obj; 56 | for (Jedis jedis : shardedJedis.getAllShards()) { 57 | try { 58 | try { 59 | jedis.quit(); 60 | } catch (Exception e) { 61 | 62 | } 63 | jedis.disconnect(); 64 | } catch (Exception e) { 65 | 66 | } 67 | } 68 | } 69 | } 70 | 71 | public boolean validateObject(final Object obj) { 72 | try { 73 | ShardedJedis jedis = (ShardedJedis) obj; 74 | for (Jedis shard : jedis.getAllShards()) { 75 | if (!shard.ping().equals("PONG")) { 76 | return false; 77 | } 78 | } 79 | return true; 80 | } catch (Exception ex) { 81 | return false; 82 | } 83 | } 84 | } 85 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/RedisInputStream.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright 2009-2010 MBTE Sweden AB. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | */ 16 | 17 | package redis.clients.util; 18 | 19 | import java.io.FilterInputStream; 20 | import java.io.IOException; 21 | import java.io.InputStream; 22 | 23 | import redis.clients.jedis.exceptions.JedisConnectionException; 24 | 25 | public class RedisInputStream extends FilterInputStream { 26 | 27 | protected final byte buf[]; 28 | 29 | protected int count, limit; 30 | 31 | public RedisInputStream(InputStream in, int size) { 32 | super(in); 33 | if (size <= 0) { 34 | throw new IllegalArgumentException("Buffer size <= 0"); 35 | } 36 | buf = new byte[size]; 37 | } 38 | 39 | public RedisInputStream(InputStream in) { 40 | this(in, 8192); 41 | } 42 | 43 | public byte readByte() throws IOException { 44 | if (count == limit) { 45 | fill(); 46 | } 47 | 48 | return buf[count++]; 49 | } 50 | 51 | public String readLine() { 52 | int b; 53 | byte c; 54 | StringBuilder sb = new StringBuilder(); 55 | 56 | try { 57 | while (true) { 58 | if (count == limit) { 59 | fill(); 60 | } 61 | if (limit == -1) 62 | break; 63 | 64 | b = buf[count++]; 65 | if (b == '\r') { 66 | if (count == limit) { 67 | fill(); 68 | } 69 | 70 | if (limit == -1) { 71 | sb.append((char) b); 72 | break; 73 | } 74 | 75 | c = buf[count++]; 76 | if (c == '\n') { 77 | break; 78 | } 79 | sb.append((char) b); 80 | sb.append((char) c); 81 | } else { 82 | sb.append((char) b); 83 | } 84 | } 85 | } catch (IOException e) { 86 | throw new JedisConnectionException(e); 87 | } 88 | String reply = sb.toString(); 89 | if (reply.length() == 0) { 90 | throw new JedisConnectionException( 91 | "It seems like server has closed the connection."); 92 | } 93 | return reply; 94 | } 95 | 96 | public int read(byte[] b, int off, int len) throws IOException { 97 | if (count == limit) { 98 | fill(); 99 | if (limit == -1) 100 | return -1; 101 | } 102 | final int length = Math.min(limit - count, len); 103 | System.arraycopy(buf, count, b, off, length); 104 | count += length; 105 | return length; 106 | } 107 | 108 | private void fill() throws IOException { 109 | limit = in.read(buf); 110 | count = 0; 111 | } 112 | } 113 | -------------------------------------------------------------------------------- /pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | org.sonatype.oss 5 | oss-parent 6 | 7 7 | 8 | 9 | 4.0.0 10 | jar 11 | redis.clients 12 | jedis 13 | 2.2.0-SNAPSHOT 14 | Jedis 15 | Jedis is a blazingly small and sane Redis java client. 16 | http://code.google.com/p/jedis/ 17 | 18 | 19 | 20 | Jedis Mailing List 21 | jedis_redis@googlegroups.com 22 | 23 | http://groups.google.com/group/jedis_redis 24 | 25 | 26 | 27 | 28 | 29 | 30 | Jedis License 31 | http://github.com/xetorthio/jedis/raw/master/LICENSE.txt 32 | repo 33 | 34 | 35 | 36 | 37 | github 38 | http://github.com/xetorthio/jedis/issues 39 | 40 | 41 | 42 | scm:git:git@github.com:xetorthio/jedis.git 43 | scm:git:git@github.com:xetorthio/jedis.git 44 | scm:git:git@github.com:xetorthio/jedis.git 45 | 46 | 47 | 48 | localhost:6379,localhost:6380 49 | 50 | 51 | 52 | 53 | junit 54 | junit 55 | 4.8.1 56 | jar 57 | test 58 | 59 | 60 | commons-pool 61 | commons-pool 62 | 1.5.5 63 | jar 64 | compile 65 | 66 | 67 | 68 | 69 | 70 | 71 | org.apache.maven.plugins 72 | maven-compiler-plugin 73 | 2.0.2 74 | 75 | 1.5 76 | 1.5 77 | 78 | 79 | 80 | org.apache.maven.plugins 81 | maven-surefire-plugin 82 | 2.6 83 | 84 | 85 | ${redis-hosts} 86 | 87 | 88 | 89 | 90 | org.apache.maven.plugins 91 | maven-source-plugin 92 | 2.1.2 93 | 94 | true 95 | 96 | 97 | 98 | org.apache.maven.plugins 99 | maven-javadoc-plugin 100 | 2.7 101 | 102 | true 103 | 104 | 105 | 106 | org.apache.maven.plugins 107 | maven-release-plugin 108 | 2.0-beta-9 109 | 110 | 111 | 112 | 113 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Pipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import redis.clients.jedis.exceptions.JedisDataException; 4 | 5 | import java.util.ArrayList; 6 | import java.util.List; 7 | 8 | public class Pipeline extends MultiKeyPipelineBase { 9 | 10 | private MultiResponseBuilder currentMulti; 11 | 12 | private class MultiResponseBuilder extends Builder>{ 13 | private List> responses = new ArrayList>(); 14 | 15 | @Override 16 | public List build(Object data) { 17 | @SuppressWarnings("unchecked") 18 | List list = (List)data; 19 | List values = new ArrayList(); 20 | 21 | if(list.size() != responses.size()){ 22 | throw new JedisDataException("Expected data size " + responses.size() + " but was " + list.size()); 23 | } 24 | 25 | for(int i=0;i response = responses.get(i); 27 | response.set(list.get(i)); 28 | values.add(response.get()); 29 | } 30 | return values; 31 | } 32 | 33 | public void addResponse(Response response){ 34 | responses.add(response); 35 | } 36 | } 37 | 38 | @Override 39 | protected Response getResponse(Builder builder) { 40 | if(currentMulti != null){ 41 | super.getResponse(BuilderFactory.STRING); //Expected QUEUED 42 | 43 | Response lr = new Response(builder); 44 | currentMulti.addResponse(lr); 45 | return lr; 46 | } 47 | else{ 48 | return super.getResponse(builder); 49 | } 50 | } 51 | 52 | public void setClient(Client client) { 53 | this.client = client; 54 | } 55 | 56 | @Override 57 | protected Client getClient(byte[] key) { 58 | return client; 59 | } 60 | 61 | @Override 62 | protected Client getClient(String key) { 63 | return client; 64 | } 65 | 66 | /** 67 | * Syncronize pipeline by reading all responses. This operation close the 68 | * pipeline. In order to get return values from pipelined commands, capture 69 | * the different Response of the commands you execute. 70 | */ 71 | public void sync() { 72 | List unformatted = client.getAll(); 73 | for (Object o : unformatted) { 74 | generateResponse(o); 75 | } 76 | } 77 | 78 | /** 79 | * Syncronize pipeline by reading all responses. This operation close the 80 | * pipeline. Whenever possible try to avoid using this version and use 81 | * Pipeline.sync() as it won't go through all the responses and generate the 82 | * right response type (usually it is a waste of time). 83 | * 84 | * @return A list of all the responses in the order you executed them. 85 | */ 86 | public List syncAndReturnAll() { 87 | List unformatted = client.getAll(); 88 | List formatted = new ArrayList(); 89 | 90 | for (Object o : unformatted) { 91 | try { 92 | formatted.add(generateResponse(o).get()); 93 | } catch (JedisDataException e) { 94 | formatted.add(e); 95 | } 96 | } 97 | return formatted; 98 | } 99 | 100 | public Response discard() { 101 | client.discard(); 102 | return getResponse(BuilderFactory.STRING); 103 | } 104 | 105 | public Response> exec() { 106 | client.exec(); 107 | Response> response = super.getResponse(currentMulti); 108 | currentMulti = null; 109 | return response; 110 | } 111 | 112 | public Response multi() { 113 | client.multi(); 114 | Response response = getResponse(BuilderFactory.STRING); //Expecting OK 115 | currentMulti = new MultiResponseBuilder(); 116 | return response; 117 | } 118 | 119 | } 120 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/ControlCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.List; 4 | 5 | import org.junit.Test; 6 | 7 | import redis.clients.jedis.DebugParams; 8 | import redis.clients.jedis.Jedis; 9 | import redis.clients.jedis.JedisMonitor; 10 | import redis.clients.jedis.exceptions.JedisDataException; 11 | 12 | public class ControlCommandsTest extends JedisCommandTestBase { 13 | @Test 14 | public void save() { 15 | String status = jedis.save(); 16 | assertEquals("OK", status); 17 | } 18 | 19 | @Test 20 | public void bgsave() { 21 | try { 22 | String status = jedis.bgsave(); 23 | assertEquals("Background saving started", status); 24 | } catch (JedisDataException e) { 25 | assertTrue("ERR Background save already in progress" 26 | .equalsIgnoreCase(e.getMessage())); 27 | } 28 | } 29 | 30 | @Test 31 | public void bgrewriteaof() { 32 | String scheduled = "Background append only file rewriting scheduled"; 33 | String started = "Background append only file rewriting started"; 34 | 35 | String status = jedis.bgrewriteaof(); 36 | 37 | boolean ok = status.equals(scheduled) || status.equals(started); 38 | assertTrue(ok); 39 | } 40 | 41 | @Test 42 | public void lastsave() throws InterruptedException { 43 | long before = jedis.lastsave(); 44 | String st = ""; 45 | while (!st.equals("OK")) { 46 | try { 47 | Thread.sleep(1000); 48 | st = jedis.save(); 49 | } catch (JedisDataException e) { 50 | 51 | } 52 | } 53 | long after = jedis.lastsave(); 54 | assertTrue((after - before) > 0); 55 | } 56 | 57 | @Test 58 | public void info() { 59 | String info = jedis.info(); 60 | assertNotNull(info); 61 | info = jedis.info("server"); 62 | assertNotNull(info); 63 | } 64 | 65 | @Test 66 | public void monitor() { 67 | new Thread(new Runnable() { 68 | public void run() { 69 | Jedis j = new Jedis("localhost"); 70 | j.auth("foobared"); 71 | for (int i = 0; i < 4; i++) { 72 | j.incr("foobared"); 73 | } 74 | try { 75 | Thread.sleep(2500); 76 | } catch (InterruptedException e) { 77 | } 78 | j.incr("foobared"); 79 | j.disconnect(); 80 | } 81 | }).start(); 82 | 83 | jedis.monitor(new JedisMonitor() { 84 | private int count = 0; 85 | 86 | public void onCommand(String command) { 87 | if (command.contains("INCR")) { 88 | count++; 89 | } 90 | if (count == 5) { 91 | client.disconnect(); 92 | } 93 | } 94 | }); 95 | } 96 | 97 | @Test 98 | public void configGet() { 99 | List info = jedis.configGet("m*"); 100 | assertNotNull(info); 101 | } 102 | 103 | @Test 104 | public void configSet() { 105 | List info = jedis.configGet("maxmemory"); 106 | String memory = info.get(1); 107 | String status = jedis.configSet("maxmemory", "200"); 108 | assertEquals("OK", status); 109 | jedis.configSet("maxmemory", memory); 110 | } 111 | 112 | @Test 113 | public void sync() { 114 | jedis.sync(); 115 | } 116 | 117 | @Test 118 | public void debug() { 119 | jedis.set("foo", "bar"); 120 | String resp = jedis.debug(DebugParams.OBJECT("foo")); 121 | assertNotNull(resp); 122 | resp = jedis.debug(DebugParams.RELOAD()); 123 | assertNotNull(resp); 124 | } 125 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Jedis 2 | 3 | Jedis is a blazingly small and sane [Redis](http://github.com/antirez/redis "Redis") java client. 4 | 5 | Jedis was conceived to be EASY to use. 6 | 7 | Jedis is fully compatible with redis 2.0.0. 8 | 9 | ## I want to persist my objects in Redis. How can I do it? 10 | You should definitely check [JOhm](http://github.com/xetorthio/johm "JOhm")! 11 | And of course, you can always serialize it and store it. 12 | 13 | ## Is there a Groovy client? 14 | 15 | Yes. You can use Jedis if you want, but I recommend [Gedis](http://github.com/xetorthio/gedis "Gedis"), which is Jedis but with a nicer groovy-like interface :) 16 | 17 | ## Community 18 | 19 | Meet us on IRC: ##jedis on freenode.net 20 | 21 | Join the mailing-list at [http://groups.google.com/group/jedis_redis](http://groups.google.com/group/jedis_redis) 22 | 23 | ## So what can I do with Jedis? 24 | All of the following redis features are supported: 25 | 26 | - Sorting 27 | - Connection handling 28 | - Commands operating on any kind of values 29 | - Commands operating on string values 30 | - Commands operating on hashes 31 | - Commands operating on lists 32 | - Commands operating on sets 33 | - Commands operating on sorted sets 34 | - Transactions 35 | - Pipelining 36 | - Publish/Subscribe 37 | - Persistence control commands 38 | - Remote server control commands 39 | - Connection pooling 40 | - Sharding (MD5, MurmureHash) 41 | - Key-tags for sharding 42 | - Sharding with pipelining 43 | 44 | ## How do I use it? 45 | 46 | You can download the latest build at: 47 | http://github.com/xetorthio/jedis/downloads 48 | 49 | Or use it as a maven dependency: 50 | 51 | ```xml 52 | 53 | redis.clients 54 | jedis 55 | 2.0.0 56 | jar 57 | compile 58 | 59 | ``` 60 | 61 | To use it just: 62 | 63 | ```java 64 | Jedis jedis = new Jedis("localhost"); 65 | jedis.set("foo", "bar"); 66 | String value = jedis.get("foo"); 67 | ``` 68 | 69 | For more usage examples check the tests. 70 | 71 | Please check the [wiki](http://github.com/xetorthio/jedis/wiki "wiki"). There are lots of cool things you should know, including information about connection pooling. 72 | 73 | And you are done! 74 | 75 | ## I want to contribute! 76 | 77 | That is great! Just fork the project in github. Create a topic branch, write some code, and add some tests for your new code. 78 | 79 | To run the tests: 80 | 81 | - Use the latest redis master branch. 82 | 83 | - Run ```make test```. This will run 2 instances of redis. We use 2 redis servers, one on default port (6379) and the other one on (6380). Both have authentication enabled with default password (foobared). This way we can test both sharding and auth command. 84 | 85 | Thanks for helping! 86 | 87 | ## License 88 | 89 | Copyright (c) 2011 Jonathan Leibiusky 90 | 91 | Permission is hereby granted, free of charge, to any person 92 | obtaining a copy of this software and associated documentation 93 | files (the "Software"), to deal in the Software without 94 | restriction, including without limitation the rights to use, 95 | copy, modify, merge, publish, distribute, sublicense, and/or sell 96 | copies of the Software, and to permit persons to whom the 97 | Software is furnished to do so, subject to the following 98 | conditions: 99 | 100 | The above copyright notice and this permission notice shall be 101 | included in all copies or substantial portions of the Software. 102 | 103 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 104 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 105 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 106 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 107 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 108 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 109 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 110 | OTHER DEALINGS IN THE SOFTWARE. 111 | 112 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/ProtocolTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.io.BufferedInputStream; 4 | import java.io.ByteArrayInputStream; 5 | import java.io.IOException; 6 | import java.io.InputStream; 7 | import java.io.PipedInputStream; 8 | import java.io.PipedOutputStream; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | 12 | import org.junit.Test; 13 | 14 | import redis.clients.jedis.Protocol; 15 | import redis.clients.util.RedisInputStream; 16 | import redis.clients.util.RedisOutputStream; 17 | import redis.clients.util.SafeEncoder; 18 | 19 | public class ProtocolTest extends JedisTestBase { 20 | @Test 21 | public void buildACommand() throws IOException { 22 | PipedInputStream pis = new PipedInputStream(); 23 | BufferedInputStream bis = new BufferedInputStream(pis); 24 | PipedOutputStream pos = new PipedOutputStream(pis); 25 | RedisOutputStream ros = new RedisOutputStream(pos); 26 | 27 | Protocol.sendCommand(ros, Protocol.Command.GET, 28 | "SOMEKEY".getBytes(Protocol.CHARSET)); 29 | ros.flush(); 30 | pos.close(); 31 | String expectedCommand = "*2\r\n$3\r\nGET\r\n$7\r\nSOMEKEY\r\n"; 32 | 33 | int b; 34 | StringBuilder sb = new StringBuilder(); 35 | while ((b = bis.read()) != -1) { 36 | sb.append((char) b); 37 | } 38 | 39 | assertEquals(expectedCommand, sb.toString()); 40 | } 41 | 42 | @Test 43 | public void bulkReply() { 44 | InputStream is = new ByteArrayInputStream("$6\r\nfoobar\r\n".getBytes()); 45 | byte[] response = (byte[]) Protocol.read(new RedisInputStream(is)); 46 | assertArrayEquals(SafeEncoder.encode("foobar"), response); 47 | } 48 | 49 | @Test 50 | public void fragmentedBulkReply() { 51 | FragmentedByteArrayInputStream fis = new FragmentedByteArrayInputStream( 52 | "$30\r\n012345678901234567890123456789\r\n".getBytes()); 53 | byte[] response = (byte[]) Protocol.read(new RedisInputStream(fis)); 54 | assertArrayEquals(SafeEncoder.encode("012345678901234567890123456789"), 55 | response); 56 | } 57 | 58 | @Test 59 | public void nullBulkReply() { 60 | InputStream is = new ByteArrayInputStream("$-1\r\n".getBytes()); 61 | String response = (String) Protocol.read(new RedisInputStream(is)); 62 | assertEquals(null, response); 63 | } 64 | 65 | @Test 66 | public void singleLineReply() { 67 | InputStream is = new ByteArrayInputStream("+OK\r\n".getBytes()); 68 | byte[] response = (byte[]) Protocol.read(new RedisInputStream(is)); 69 | assertArrayEquals(SafeEncoder.encode("OK"), response); 70 | } 71 | 72 | @Test 73 | public void integerReply() { 74 | InputStream is = new ByteArrayInputStream(":123\r\n".getBytes()); 75 | long response = (Long) Protocol.read(new RedisInputStream(is)); 76 | assertEquals(123, response); 77 | } 78 | 79 | @SuppressWarnings("unchecked") 80 | @Test 81 | public void multiBulkReply() { 82 | InputStream is = new ByteArrayInputStream( 83 | "*4\r\n$3\r\nfoo\r\n$3\r\nbar\r\n$5\r\nHello\r\n$5\r\nWorld\r\n" 84 | .getBytes()); 85 | List response = (List) Protocol 86 | .read(new RedisInputStream(is)); 87 | List expected = new ArrayList(); 88 | expected.add(SafeEncoder.encode("foo")); 89 | expected.add(SafeEncoder.encode("bar")); 90 | expected.add(SafeEncoder.encode("Hello")); 91 | expected.add(SafeEncoder.encode("World")); 92 | 93 | assertEquals(expected, response); 94 | } 95 | 96 | @SuppressWarnings("unchecked") 97 | @Test 98 | public void nullMultiBulkReply() { 99 | InputStream is = new ByteArrayInputStream("*-1\r\n".getBytes()); 100 | List response = (List) Protocol 101 | .read(new RedisInputStream(is)); 102 | assertNull(response); 103 | } 104 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisPoolConfig.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import org.apache.commons.pool.impl.GenericObjectPool.Config; 4 | 5 | /** 6 | * Subclass of org.apache.commons.pool.impl.GenericObjectPool.Config that 7 | * includes getters/setters so it can be more easily configured by Spring and 8 | * other IoC frameworks. 9 | * 10 | * Spring example: 11 | * 12 | * 14 | * 15 | * 17 | * 19 | * 20 | * For information on parameters refer to: 21 | * 22 | * http://commons.apache.org/pool/apidocs/org/apache/commons/pool/impl/ 23 | * GenericObjectPool.html 24 | */ 25 | public class JedisPoolConfig extends Config { 26 | public JedisPoolConfig() { 27 | // defaults to make your life with connection pool easier :) 28 | setTestWhileIdle(true); 29 | setMinEvictableIdleTimeMillis(60000); 30 | setTimeBetweenEvictionRunsMillis(30000); 31 | setNumTestsPerEvictionRun(-1); 32 | } 33 | 34 | public int getMaxIdle() { 35 | return maxIdle; 36 | } 37 | 38 | public void setMaxIdle(int maxIdle) { 39 | this.maxIdle = maxIdle; 40 | } 41 | 42 | public int getMinIdle() { 43 | return minIdle; 44 | } 45 | 46 | public void setMinIdle(int minIdle) { 47 | this.minIdle = minIdle; 48 | } 49 | 50 | public int getMaxActive() { 51 | return maxActive; 52 | } 53 | 54 | public void setMaxActive(int maxActive) { 55 | this.maxActive = maxActive; 56 | } 57 | 58 | public long getMaxWait() { 59 | return maxWait; 60 | } 61 | 62 | public void setMaxWait(long maxWait) { 63 | this.maxWait = maxWait; 64 | } 65 | 66 | public byte getWhenExhaustedAction() { 67 | return whenExhaustedAction; 68 | } 69 | 70 | public void setWhenExhaustedAction(byte whenExhaustedAction) { 71 | this.whenExhaustedAction = whenExhaustedAction; 72 | } 73 | 74 | public boolean isTestOnBorrow() { 75 | return testOnBorrow; 76 | } 77 | 78 | public void setTestOnBorrow(boolean testOnBorrow) { 79 | this.testOnBorrow = testOnBorrow; 80 | } 81 | 82 | public boolean isTestOnReturn() { 83 | return testOnReturn; 84 | } 85 | 86 | public void setTestOnReturn(boolean testOnReturn) { 87 | this.testOnReturn = testOnReturn; 88 | } 89 | 90 | public boolean isTestWhileIdle() { 91 | return testWhileIdle; 92 | } 93 | 94 | public void setTestWhileIdle(boolean testWhileIdle) { 95 | this.testWhileIdle = testWhileIdle; 96 | } 97 | 98 | public long getTimeBetweenEvictionRunsMillis() { 99 | return timeBetweenEvictionRunsMillis; 100 | } 101 | 102 | public void setTimeBetweenEvictionRunsMillis( 103 | long timeBetweenEvictionRunsMillis) { 104 | this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis; 105 | } 106 | 107 | public int getNumTestsPerEvictionRun() { 108 | return numTestsPerEvictionRun; 109 | } 110 | 111 | public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) { 112 | this.numTestsPerEvictionRun = numTestsPerEvictionRun; 113 | } 114 | 115 | public long getMinEvictableIdleTimeMillis() { 116 | return minEvictableIdleTimeMillis; 117 | } 118 | 119 | public void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) { 120 | this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis; 121 | } 122 | 123 | public long getSoftMinEvictableIdleTimeMillis() { 124 | return softMinEvictableIdleTimeMillis; 125 | } 126 | 127 | public void setSoftMinEvictableIdleTimeMillis( 128 | long softMinEvictableIdleTimeMillis) { 129 | this.softMinEvictableIdleTimeMillis = softMinEvictableIdleTimeMillis; 130 | } 131 | 132 | } 133 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/Sharded.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | import java.util.Collection; 4 | import java.util.Collections; 5 | import java.util.LinkedHashMap; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.SortedMap; 9 | import java.util.TreeMap; 10 | import java.util.regex.Matcher; 11 | import java.util.regex.Pattern; 12 | 13 | public class Sharded> { 14 | 15 | public static final int DEFAULT_WEIGHT = 1; 16 | private TreeMap nodes; 17 | private final Hashing algo; 18 | private final Map, R> resources = new LinkedHashMap, R>(); 19 | 20 | /** 21 | * The default pattern used for extracting a key tag. The pattern must have 22 | * a group (between parenthesis), which delimits the tag to be hashed. A 23 | * null pattern avoids applying the regular expression for each lookup, 24 | * improving performance a little bit is key tags aren't being used. 25 | */ 26 | private Pattern tagPattern = null; 27 | // the tag is anything between {} 28 | public static final Pattern DEFAULT_KEY_TAG_PATTERN = Pattern 29 | .compile("\\{(.+?)\\}"); 30 | 31 | public Sharded(List shards) { 32 | this(shards, Hashing.MURMUR_HASH); // MD5 is really not good as we works 33 | // with 64-bits not 128 34 | } 35 | 36 | public Sharded(List shards, Hashing algo) { 37 | this.algo = algo; 38 | initialize(shards); 39 | } 40 | 41 | public Sharded(List shards, Pattern tagPattern) { 42 | this(shards, Hashing.MURMUR_HASH, tagPattern); // MD5 is really not good 43 | // as we works with 44 | // 64-bits not 128 45 | } 46 | 47 | public Sharded(List shards, Hashing algo, Pattern tagPattern) { 48 | this.algo = algo; 49 | this.tagPattern = tagPattern; 50 | initialize(shards); 51 | } 52 | 53 | private void initialize(List shards) { 54 | nodes = new TreeMap(); 55 | 56 | for (int i = 0; i != shards.size(); ++i) { 57 | final S shardInfo = shards.get(i); 58 | if (shardInfo.getName() == null) 59 | for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { 60 | nodes.put(this.algo.hash("SHARD-" + i + "-NODE-" + n), shardInfo); 61 | } 62 | else 63 | for (int n = 0; n < 160 * shardInfo.getWeight(); n++) { 64 | nodes.put(this.algo.hash(shardInfo.getName() + "*" + shardInfo.getWeight() + n), shardInfo); 65 | } 66 | resources.put(shardInfo, shardInfo.createResource()); 67 | } 68 | } 69 | 70 | public R getShard(byte[] key) { 71 | return resources.get(getShardInfo(key)); 72 | } 73 | 74 | public R getShard(String key) { 75 | return resources.get(getShardInfo(key)); 76 | } 77 | 78 | public S getShardInfo(byte[] key) { 79 | SortedMap tail = nodes.tailMap(algo.hash(key)); 80 | if (tail.isEmpty()) { 81 | return nodes.get(nodes.firstKey()); 82 | } 83 | return tail.get(tail.firstKey()); 84 | } 85 | 86 | public S getShardInfo(String key) { 87 | return getShardInfo(SafeEncoder.encode(getKeyTag(key))); 88 | } 89 | 90 | /** 91 | * A key tag is a special pattern inside a key that, if preset, is the only 92 | * part of the key hashed in order to select the server for this key. 93 | * 94 | * @see http://code.google.com/p/redis/wiki/FAQ#I 95 | * 'm_using_some_form_of_key_hashing_for_partitioning,_but_wh 96 | * @param key 97 | * @return The tag if it exists, or the original key 98 | */ 99 | public String getKeyTag(String key) { 100 | if (tagPattern != null) { 101 | Matcher m = tagPattern.matcher(key); 102 | if (m.find()) 103 | return m.group(1); 104 | } 105 | return key; 106 | } 107 | 108 | public Collection getAllShardInfo() { 109 | return Collections.unmodifiableCollection(nodes.values()); 110 | } 111 | 112 | public Collection getAllShards() { 113 | return Collections.unmodifiableCollection(resources.values()); 114 | } 115 | } 116 | 117 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/JedisByteHashMap.java: -------------------------------------------------------------------------------- 1 | package redis.clients.util; 2 | 3 | import java.io.Serializable; 4 | import java.util.Arrays; 5 | import java.util.Collection; 6 | import java.util.HashMap; 7 | import java.util.HashSet; 8 | import java.util.Iterator; 9 | import java.util.Map; 10 | import java.util.Set; 11 | 12 | public class JedisByteHashMap implements Map, Cloneable, 13 | Serializable { 14 | private static final long serialVersionUID = -6971431362627219416L; 15 | private Map internalMap = new HashMap(); 16 | 17 | public void clear() { 18 | internalMap.clear(); 19 | } 20 | 21 | public boolean containsKey(Object key) { 22 | if (key instanceof byte[]) 23 | return internalMap.containsKey(new ByteArrayWrapper((byte[]) key)); 24 | return internalMap.containsKey(key); 25 | } 26 | 27 | public boolean containsValue(Object value) { 28 | return internalMap.containsValue(value); 29 | } 30 | 31 | public Set> entrySet() { 32 | Iterator> iterator = internalMap 33 | .entrySet().iterator(); 34 | HashSet> hashSet = new HashSet>(); 35 | while (iterator.hasNext()) { 36 | Entry entry = iterator.next(); 37 | hashSet.add(new JedisByteEntry(entry.getKey().data, entry 38 | .getValue())); 39 | } 40 | return hashSet; 41 | } 42 | 43 | public byte[] get(Object key) { 44 | if (key instanceof byte[]) 45 | return internalMap.get(new ByteArrayWrapper((byte[]) key)); 46 | return internalMap.get(key); 47 | } 48 | 49 | public boolean isEmpty() { 50 | return internalMap.isEmpty(); 51 | } 52 | 53 | public Set keySet() { 54 | Set keySet = new HashSet(); 55 | Iterator iterator = internalMap.keySet().iterator(); 56 | while (iterator.hasNext()) { 57 | keySet.add(iterator.next().data); 58 | } 59 | return keySet; 60 | } 61 | 62 | public byte[] put(byte[] key, byte[] value) { 63 | return internalMap.put(new ByteArrayWrapper(key), value); 64 | } 65 | 66 | @SuppressWarnings("unchecked") 67 | public void putAll(Map m) { 68 | Iterator iterator = m.entrySet().iterator(); 69 | while (iterator.hasNext()) { 70 | Entry next = (Entry) iterator 71 | .next(); 72 | internalMap.put(new ByteArrayWrapper(next.getKey()), next 73 | .getValue()); 74 | } 75 | } 76 | 77 | public byte[] remove(Object key) { 78 | if (key instanceof byte[]) 79 | return internalMap.remove(new ByteArrayWrapper((byte[]) key)); 80 | return internalMap.remove(key); 81 | } 82 | 83 | public int size() { 84 | return internalMap.size(); 85 | } 86 | 87 | public Collection values() { 88 | return internalMap.values(); 89 | } 90 | 91 | private static final class ByteArrayWrapper { 92 | private final byte[] data; 93 | 94 | public ByteArrayWrapper(byte[] data) { 95 | if (data == null) { 96 | throw new NullPointerException(); 97 | } 98 | this.data = data; 99 | } 100 | 101 | public boolean equals(Object other) { 102 | if (!(other instanceof ByteArrayWrapper)) { 103 | return false; 104 | } 105 | return Arrays.equals(data, ((ByteArrayWrapper) other).data); 106 | } 107 | 108 | public int hashCode() { 109 | return Arrays.hashCode(data); 110 | } 111 | } 112 | 113 | private static final class JedisByteEntry implements Entry { 114 | private byte[] value; 115 | private byte[] key; 116 | 117 | public JedisByteEntry(byte[] key, byte[] value) { 118 | this.key = key; 119 | this.value = value; 120 | } 121 | 122 | public byte[] getKey() { 123 | return this.key; 124 | } 125 | 126 | public byte[] getValue() { 127 | return this.value; 128 | } 129 | 130 | public byte[] setValue(byte[] value) { 131 | this.value = value; 132 | return value; 133 | } 134 | 135 | } 136 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BinaryJedisPubSub.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import static redis.clients.jedis.Protocol.Keyword.MESSAGE; 4 | import static redis.clients.jedis.Protocol.Keyword.PMESSAGE; 5 | import static redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE; 6 | import static redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE; 7 | import static redis.clients.jedis.Protocol.Keyword.SUBSCRIBE; 8 | import static redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE; 9 | 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import redis.clients.jedis.exceptions.JedisException; 14 | 15 | public abstract class BinaryJedisPubSub { 16 | private int subscribedChannels = 0; 17 | private Client client; 18 | 19 | public abstract void onMessage(byte[] channel, byte[] message); 20 | 21 | public abstract void onPMessage(byte[] pattern, byte[] channel, 22 | byte[] message); 23 | 24 | public abstract void onSubscribe(byte[] channel, int subscribedChannels); 25 | 26 | public abstract void onUnsubscribe(byte[] channel, int subscribedChannels); 27 | 28 | public abstract void onPUnsubscribe(byte[] pattern, int subscribedChannels); 29 | 30 | public abstract void onPSubscribe(byte[] pattern, int subscribedChannels); 31 | 32 | public void unsubscribe() { 33 | client.unsubscribe(); 34 | client.flush(); 35 | } 36 | 37 | public void unsubscribe(byte[]... channels) { 38 | client.unsubscribe(channels); 39 | client.flush(); 40 | } 41 | 42 | public void subscribe(byte[]... channels) { 43 | client.subscribe(channels); 44 | client.flush(); 45 | } 46 | 47 | public void psubscribe(byte[]... patterns) { 48 | client.psubscribe(patterns); 49 | client.flush(); 50 | } 51 | 52 | public void punsubscribe() { 53 | client.punsubscribe(); 54 | client.flush(); 55 | } 56 | 57 | public void punsubscribe(byte[]... patterns) { 58 | client.punsubscribe(patterns); 59 | client.flush(); 60 | } 61 | 62 | public boolean isSubscribed() { 63 | return subscribedChannels > 0; 64 | } 65 | 66 | public void proceedWithPatterns(Client client, byte[]... patterns) { 67 | this.client = client; 68 | client.psubscribe(patterns); 69 | process(client); 70 | } 71 | 72 | public void proceed(Client client, byte[]... channels) { 73 | this.client = client; 74 | client.subscribe(channels); 75 | process(client); 76 | } 77 | 78 | private void process(Client client) { 79 | do { 80 | List reply = client.getObjectMultiBulkReply(); 81 | final Object firstObj = reply.get(0); 82 | if (!(firstObj instanceof byte[])) { 83 | throw new JedisException("Unknown message type: " + firstObj); 84 | } 85 | final byte[] resp = (byte[]) firstObj; 86 | if (Arrays.equals(SUBSCRIBE.raw, resp)) { 87 | subscribedChannels = ((Long) reply.get(2)).intValue(); 88 | final byte[] bchannel = (byte[]) reply.get(1); 89 | onSubscribe(bchannel, subscribedChannels); 90 | } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { 91 | subscribedChannels = ((Long) reply.get(2)).intValue(); 92 | final byte[] bchannel = (byte[]) reply.get(1); 93 | onUnsubscribe(bchannel, subscribedChannels); 94 | } else if (Arrays.equals(MESSAGE.raw, resp)) { 95 | final byte[] bchannel = (byte[]) reply.get(1); 96 | final byte[] bmesg = (byte[]) reply.get(2); 97 | onMessage(bchannel, bmesg); 98 | } else if (Arrays.equals(PMESSAGE.raw, resp)) { 99 | final byte[] bpattern = (byte[]) reply.get(1); 100 | final byte[] bchannel = (byte[]) reply.get(2); 101 | final byte[] bmesg = (byte[]) reply.get(3); 102 | onPMessage(bpattern, bchannel, bmesg); 103 | } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { 104 | subscribedChannels = ((Long) reply.get(2)).intValue(); 105 | final byte[] bpattern = (byte[]) reply.get(1); 106 | onPSubscribe(bpattern, subscribedChannels); 107 | } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { 108 | subscribedChannels = ((Long) reply.get(2)).intValue(); 109 | final byte[] bpattern = (byte[]) reply.get(1); 110 | onPUnsubscribe(bpattern, subscribedChannels); 111 | } else { 112 | throw new JedisException("Unknown message type: " + firstObj); 113 | } 114 | } while (isSubscribed()); 115 | } 116 | 117 | public int getSubscribedChannels() { 118 | return subscribedChannels; 119 | } 120 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/ScriptingCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.junit.Test; 7 | 8 | import redis.clients.jedis.exceptions.JedisDataException; 9 | import redis.clients.util.SafeEncoder; 10 | 11 | public class ScriptingCommandsTest extends JedisCommandTestBase { 12 | 13 | @SuppressWarnings("unchecked") 14 | @Test 15 | public void evalMultiBulk() { 16 | String script = "return {KEYS[1],KEYS[2],ARGV[1],ARGV[2]}"; 17 | List keys = new ArrayList(); 18 | keys.add("key1"); 19 | keys.add("key2"); 20 | 21 | List args = new ArrayList(); 22 | args.add("first"); 23 | args.add("second"); 24 | 25 | List response = (List) jedis.eval(script, keys, args); 26 | 27 | assertEquals(4, response.size()); 28 | assertEquals("key1", response.get(0)); 29 | assertEquals("key2", response.get(1)); 30 | assertEquals("first", response.get(2)); 31 | assertEquals("second", response.get(3)); 32 | } 33 | 34 | @Test 35 | public void evalBulk() { 36 | String script = "return KEYS[1]"; 37 | List keys = new ArrayList(); 38 | keys.add("key1"); 39 | 40 | List args = new ArrayList(); 41 | args.add("first"); 42 | 43 | String response = (String) jedis.eval(script, keys, args); 44 | 45 | assertEquals("key1", response); 46 | } 47 | 48 | @Test 49 | public void evalInt() { 50 | String script = "return 2"; 51 | List keys = new ArrayList(); 52 | keys.add("key1"); 53 | 54 | Long response = (Long) jedis 55 | .eval(script, keys, new ArrayList()); 56 | 57 | assertEquals(new Long(2), response); 58 | } 59 | 60 | @Test 61 | public void evalNoArgs() { 62 | String script = "return KEYS[1]"; 63 | List keys = new ArrayList(); 64 | keys.add("key1"); 65 | String response = (String) jedis.eval(script, keys, 66 | new ArrayList()); 67 | 68 | assertEquals("key1", response); 69 | } 70 | 71 | @Test 72 | public void evalsha() { 73 | jedis.set("foo", "bar"); 74 | jedis.eval("return redis.call('get','foo')"); 75 | String result = (String) jedis 76 | .evalsha("6b1bf486c81ceb7edf3c093f4c48582e38c0e791"); 77 | 78 | assertEquals("bar", result); 79 | } 80 | 81 | @Test(expected = JedisDataException.class) 82 | public void evalshaShaNotFound() { 83 | jedis.evalsha("ffffffffffffffffffffffffffffffffffffffff"); 84 | } 85 | 86 | @Test 87 | public void scriptFlush() { 88 | jedis.set("foo", "bar"); 89 | jedis.eval("return redis.call('get','foo')"); 90 | jedis.scriptFlush(); 91 | assertFalse(jedis 92 | .scriptExists("6b1bf486c81ceb7edf3c093f4c48582e38c0e791")); 93 | } 94 | 95 | @Test 96 | public void scriptExists() { 97 | jedis.scriptLoad("return redis.call('get','foo')"); 98 | List exists = jedis.scriptExists( 99 | "ffffffffffffffffffffffffffffffffffffffff", 100 | "6b1bf486c81ceb7edf3c093f4c48582e38c0e791"); 101 | assertFalse(exists.get(0)); 102 | assertTrue(exists.get(1)); 103 | } 104 | 105 | @Test 106 | public void scriptExistsBinary() { 107 | jedis.scriptLoad(SafeEncoder.encode("return redis.call('get','foo')")); 108 | List exists = jedis.scriptExists( 109 | SafeEncoder.encode("ffffffffffffffffffffffffffffffffffffffff"), 110 | SafeEncoder.encode("6b1bf486c81ceb7edf3c093f4c48582e38c0e791")); 111 | assertEquals(new Long(0), exists.get(0)); 112 | assertEquals(new Long(1), exists.get(1)); 113 | } 114 | 115 | @Test 116 | public void scriptLoad() { 117 | jedis.scriptLoad("return redis.call('get','foo')"); 118 | assertTrue(jedis 119 | .scriptExists("6b1bf486c81ceb7edf3c093f4c48582e38c0e791")); 120 | } 121 | 122 | @Test 123 | public void scriptLoadBinary() { 124 | jedis.scriptLoad(SafeEncoder.encode("return redis.call('get','foo')")); 125 | List exists = jedis.scriptExists(SafeEncoder 126 | .encode("6b1bf486c81ceb7edf3c093f4c48582e38c0e791")); 127 | assertEquals(new Long(1), exists.get(0)); 128 | } 129 | 130 | @Test 131 | public void scriptKill() { 132 | try { 133 | jedis.scriptKill(); 134 | } catch (JedisDataException e) { 135 | assertTrue(e.getMessage().contains( 136 | "No scripts in execution right now.")); 137 | } 138 | } 139 | 140 | @Test 141 | public void scriptEvalReturnNullValues() { 142 | String script = "return {redis.call('hget',KEYS[1],ARGV[1]),redis.call('hget',KEYS[2],ARGV[2])}"; 143 | jedis.eval(script, 2, "key1", "key2", "1", "1"); 144 | } 145 | 146 | @Test 147 | public void scriptEvalShaReturnNullValues() { 148 | String script = "return {redis.call('hget',KEYS[1],ARGV[1]),redis.call('hget',KEYS[2],ARGV[2])}"; 149 | String sha = jedis.scriptLoad(script); 150 | jedis.evalsha(sha, 2, "key1", "key2", "1", "1"); 151 | } 152 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/ShardedJedisPipelineTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import static junit.framework.Assert.assertEquals; 4 | import static junit.framework.Assert.assertNull; 5 | import static org.junit.Assert.assertFalse; 6 | import static org.junit.Assert.assertNotNull; 7 | 8 | import java.io.UnsupportedEncodingException; 9 | import java.util.ArrayList; 10 | import java.util.List; 11 | import java.util.Map; 12 | import java.util.Set; 13 | import java.util.UUID; 14 | 15 | import org.junit.Before; 16 | import org.junit.Test; 17 | 18 | import redis.clients.jedis.Jedis; 19 | import redis.clients.jedis.JedisShardInfo; 20 | import redis.clients.jedis.Response; 21 | import redis.clients.jedis.ShardedJedis; 22 | import redis.clients.jedis.ShardedJedisPipeline; 23 | import redis.clients.jedis.Tuple; 24 | import redis.clients.jedis.exceptions.JedisDataException; 25 | 26 | public class ShardedJedisPipelineTest { 27 | private static HostAndPortUtil.HostAndPort redis1 = HostAndPortUtil 28 | .getRedisServers().get(0); 29 | private static HostAndPortUtil.HostAndPort redis2 = HostAndPortUtil 30 | .getRedisServers().get(1); 31 | 32 | private ShardedJedis jedis; 33 | 34 | @Before 35 | public void setUp() throws Exception { 36 | Jedis jedis = new Jedis(redis1.host, redis1.port); 37 | jedis.auth("foobared"); 38 | jedis.flushAll(); 39 | jedis.disconnect(); 40 | jedis = new Jedis(redis2.host, redis2.port); 41 | jedis.auth("foobared"); 42 | jedis.flushAll(); 43 | jedis.disconnect(); 44 | 45 | JedisShardInfo shardInfo1 = new JedisShardInfo(redis1.host, redis1.port); 46 | JedisShardInfo shardInfo2 = new JedisShardInfo(redis2.host, redis2.port); 47 | shardInfo1.setPassword("foobared"); 48 | shardInfo2.setPassword("foobared"); 49 | List shards = new ArrayList(); 50 | shards.add(shardInfo1); 51 | shards.add(shardInfo2); 52 | this.jedis = new ShardedJedis(shards); 53 | } 54 | 55 | @Test 56 | public void pipeline() throws UnsupportedEncodingException { 57 | ShardedJedisPipeline p = jedis.pipelined(); 58 | p.set("foo", "bar"); 59 | p.get("foo"); 60 | List results = p.syncAndReturnAll(); 61 | 62 | assertEquals(2, results.size()); 63 | assertEquals("OK", results.get(0)); 64 | assertEquals("bar", results.get(1)); 65 | } 66 | 67 | @Test 68 | public void pipelineResponse() { 69 | jedis.set("string", "foo"); 70 | jedis.lpush("list", "foo"); 71 | jedis.hset("hash", "foo", "bar"); 72 | jedis.zadd("zset", 1, "foo"); 73 | jedis.sadd("set", "foo"); 74 | 75 | ShardedJedisPipeline p = jedis.pipelined(); 76 | Response string = p.get("string"); 77 | Response del = p.del("string"); 78 | Response emptyString = p.get("string"); 79 | Response list = p.lpop("list"); 80 | Response hash = p.hget("hash", "foo"); 81 | Response> zset = p.zrange("zset", 0, -1); 82 | Response set = p.spop("set"); 83 | Response blist = p.exists("list"); 84 | Response zincrby = p.zincrby("zset", 1, "foo"); 85 | Response zcard = p.zcard("zset"); 86 | p.lpush("list", "bar"); 87 | Response> lrange = p.lrange("list", 0, -1); 88 | Response> hgetAll = p.hgetAll("hash"); 89 | p.sadd("set", "foo"); 90 | Response> smembers = p.smembers("set"); 91 | Response> zrangeWithScores = p.zrangeWithScores("zset", 0, 92 | -1); 93 | p.sync(); 94 | 95 | assertEquals("foo", string.get()); 96 | assertEquals(Long.valueOf(1), del.get()); 97 | assertNull(emptyString.get()); 98 | assertEquals("foo", list.get()); 99 | assertEquals("bar", hash.get()); 100 | assertEquals("foo", zset.get().iterator().next()); 101 | assertEquals("foo", set.get()); 102 | assertFalse(blist.get()); 103 | assertEquals(Double.valueOf(2), zincrby.get()); 104 | assertEquals(Long.valueOf(1), zcard.get()); 105 | assertEquals(1, lrange.get().size()); 106 | assertNotNull(hgetAll.get().get("foo")); 107 | assertEquals(1, smembers.get().size()); 108 | assertEquals(1, zrangeWithScores.get().size()); 109 | } 110 | 111 | @Test(expected = JedisDataException.class) 112 | public void pipelineResponseWithinPipeline() { 113 | jedis.set("string", "foo"); 114 | 115 | ShardedJedisPipeline p = jedis.pipelined(); 116 | Response string = p.get("string"); 117 | string.get(); 118 | p.sync(); 119 | } 120 | 121 | @Test 122 | public void canRetrieveUnsetKey() { 123 | ShardedJedisPipeline p = jedis.pipelined(); 124 | Response shouldNotExist = p.get(UUID.randomUUID().toString()); 125 | p.sync(); 126 | assertNull(shouldNotExist.get()); 127 | } 128 | } 129 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisPool.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.net.URI; 4 | 5 | import org.apache.commons.pool.BasePoolableObjectFactory; 6 | import org.apache.commons.pool.impl.GenericObjectPool; 7 | import org.apache.commons.pool.impl.GenericObjectPool.Config; 8 | 9 | import redis.clients.util.Pool; 10 | 11 | public class JedisPool extends Pool { 12 | 13 | public JedisPool(final Config poolConfig, final String host) { 14 | this(poolConfig, host, Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); 15 | } 16 | 17 | public JedisPool(String host, int port) { 18 | this(new Config(), host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); 19 | } 20 | 21 | public JedisPool(final String host) { 22 | URI uri = URI.create(host); 23 | if (uri.getScheme() != null && uri.getScheme().equals("redis")) { 24 | String h = uri.getHost(); 25 | int port = uri.getPort(); 26 | String password = uri.getUserInfo().split(":", 2)[1]; 27 | int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); 28 | this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 29 | Protocol.DEFAULT_TIMEOUT, password, database), new Config()); 30 | } else { 31 | this.internalPool = new GenericObjectPool(new JedisFactory(host, 32 | Protocol.DEFAULT_PORT, Protocol.DEFAULT_TIMEOUT, null, 33 | Protocol.DEFAULT_DATABASE), new Config()); 34 | } 35 | } 36 | 37 | public JedisPool(final URI uri) { 38 | String h = uri.getHost(); 39 | int port = uri.getPort(); 40 | String password = uri.getUserInfo().split(":", 2)[1]; 41 | int database = Integer.parseInt(uri.getPath().split("/", 2)[1]); 42 | this.internalPool = new GenericObjectPool(new JedisFactory(h, port, 43 | Protocol.DEFAULT_TIMEOUT, password, database), new Config()); 44 | } 45 | 46 | public JedisPool(final Config poolConfig, final String host, int port, 47 | int timeout, final String password) { 48 | this(poolConfig, host, port, timeout, password, Protocol.DEFAULT_DATABASE); 49 | } 50 | 51 | public JedisPool(final Config poolConfig, final String host, final int port) { 52 | this(poolConfig, host, port, Protocol.DEFAULT_TIMEOUT, null, Protocol.DEFAULT_DATABASE); 53 | } 54 | 55 | public JedisPool(final Config poolConfig, final String host, final int port, final int timeout) { 56 | this(poolConfig, host, port, timeout, null, Protocol.DEFAULT_DATABASE); 57 | } 58 | 59 | public JedisPool(final Config poolConfig, final String host, int port, int timeout, final String password, 60 | final int database) { 61 | super(poolConfig, new JedisFactory(host, port, timeout, password, database)); 62 | } 63 | 64 | 65 | public void returnBrokenResource(final BinaryJedis resource) { 66 | returnBrokenResourceObject(resource); 67 | } 68 | 69 | public void returnResource(final BinaryJedis resource) { 70 | returnResourceObject(resource); 71 | } 72 | 73 | /** 74 | * PoolableObjectFactory custom impl. 75 | */ 76 | private static class JedisFactory extends BasePoolableObjectFactory { 77 | private final String host; 78 | private final int port; 79 | private final int timeout; 80 | private final String password; 81 | private final int database; 82 | 83 | public JedisFactory(final String host, final int port, 84 | final int timeout, final String password, final int database) { 85 | super(); 86 | this.host = host; 87 | this.port = port; 88 | this.timeout = timeout; 89 | this.password = password; 90 | this.database = database; 91 | } 92 | 93 | public Object makeObject() throws Exception { 94 | final Jedis jedis = new Jedis(this.host, this.port, this.timeout); 95 | 96 | jedis.connect(); 97 | if (null != this.password) { 98 | jedis.auth(this.password); 99 | } 100 | if( database != 0 ) { 101 | jedis.select(database); 102 | } 103 | 104 | return jedis; 105 | } 106 | 107 | public void destroyObject(final Object obj) throws Exception { 108 | if (obj instanceof Jedis) { 109 | final Jedis jedis = (Jedis) obj; 110 | if (jedis.isConnected()) { 111 | try { 112 | try { 113 | jedis.quit(); 114 | } catch (Exception e) { 115 | } 116 | jedis.disconnect(); 117 | } catch (Exception e) { 118 | 119 | } 120 | } 121 | } 122 | } 123 | 124 | public boolean validateObject(final Object obj) { 125 | if (obj instanceof Jedis) { 126 | final Jedis jedis = (Jedis) obj; 127 | try { 128 | return jedis.isConnected() && jedis.ping().equals("PONG"); 129 | } catch (final Exception e) { 130 | return false; 131 | } 132 | } else { 133 | return false; 134 | } 135 | } 136 | } 137 | } 138 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/util/MurmurHash.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Licensed to the Apache Software Foundation (ASF) under one or more 3 | * contributor license agreements. See the NOTICE file distributed with 4 | * this work for additional information regarding copyright ownership. 5 | * The ASF licenses this file to You under the Apache License, Version 2.0 6 | * (the "License"); you may not use this file except in compliance with 7 | * the License. You may obtain a copy of the License at 8 | * 9 | * http://www.apache.org/licenses/LICENSE-2.0 10 | * 11 | * Unless required by applicable law or agreed to in writing, software 12 | * distributed under the License is distributed on an "AS IS" BASIS, 13 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | * See the License for the specific language governing permissions and 15 | * limitations under the License. 16 | */ 17 | 18 | package redis.clients.util; 19 | 20 | import java.nio.ByteBuffer; 21 | import java.nio.ByteOrder; 22 | 23 | /** 24 | * This is a very fast, non-cryptographic hash suitable for general hash-based 25 | * lookup. See http://murmurhash.googlepages.com/ for more details. 26 | *

27 | *

28 | * The C version of MurmurHash 2.0 found at that site was ported to Java by 29 | * Andrzej Bialecki (ab at getopt org). 30 | *

31 | */ 32 | public class MurmurHash implements Hashing { 33 | /** 34 | * Hashes bytes in an array. 35 | * 36 | * @param data 37 | * The bytes to hash. 38 | * @param seed 39 | * The seed for the hash. 40 | * @return The 32 bit hash of the bytes in question. 41 | */ 42 | public static int hash(byte[] data, int seed) { 43 | return hash(ByteBuffer.wrap(data), seed); 44 | } 45 | 46 | /** 47 | * Hashes bytes in part of an array. 48 | * 49 | * @param data 50 | * The data to hash. 51 | * @param offset 52 | * Where to start munging. 53 | * @param length 54 | * How many bytes to process. 55 | * @param seed 56 | * The seed to start with. 57 | * @return The 32-bit hash of the data in question. 58 | */ 59 | public static int hash(byte[] data, int offset, int length, int seed) { 60 | return hash(ByteBuffer.wrap(data, offset, length), seed); 61 | } 62 | 63 | /** 64 | * Hashes the bytes in a buffer from the current position to the limit. 65 | * 66 | * @param buf 67 | * The bytes to hash. 68 | * @param seed 69 | * The seed for the hash. 70 | * @return The 32 bit murmur hash of the bytes in the buffer. 71 | */ 72 | public static int hash(ByteBuffer buf, int seed) { 73 | // save byte order for later restoration 74 | ByteOrder byteOrder = buf.order(); 75 | buf.order(ByteOrder.LITTLE_ENDIAN); 76 | 77 | int m = 0x5bd1e995; 78 | int r = 24; 79 | 80 | int h = seed ^ buf.remaining(); 81 | 82 | int k; 83 | while (buf.remaining() >= 4) { 84 | k = buf.getInt(); 85 | 86 | k *= m; 87 | k ^= k >>> r; 88 | k *= m; 89 | 90 | h *= m; 91 | h ^= k; 92 | } 93 | 94 | if (buf.remaining() > 0) { 95 | ByteBuffer finish = ByteBuffer.allocate(4).order( 96 | ByteOrder.LITTLE_ENDIAN); 97 | // for big-endian version, use this first: 98 | // finish.position(4-buf.remaining()); 99 | finish.put(buf).rewind(); 100 | h ^= finish.getInt(); 101 | h *= m; 102 | } 103 | 104 | h ^= h >>> 13; 105 | h *= m; 106 | h ^= h >>> 15; 107 | 108 | buf.order(byteOrder); 109 | return h; 110 | } 111 | 112 | public static long hash64A(byte[] data, int seed) { 113 | return hash64A(ByteBuffer.wrap(data), seed); 114 | } 115 | 116 | public static long hash64A(byte[] data, int offset, int length, int seed) { 117 | return hash64A(ByteBuffer.wrap(data, offset, length), seed); 118 | } 119 | 120 | public static long hash64A(ByteBuffer buf, int seed) { 121 | ByteOrder byteOrder = buf.order(); 122 | buf.order(ByteOrder.LITTLE_ENDIAN); 123 | 124 | long m = 0xc6a4a7935bd1e995L; 125 | int r = 47; 126 | 127 | long h = seed ^ (buf.remaining() * m); 128 | 129 | long k; 130 | while (buf.remaining() >= 8) { 131 | k = buf.getLong(); 132 | 133 | k *= m; 134 | k ^= k >>> r; 135 | k *= m; 136 | 137 | h ^= k; 138 | h *= m; 139 | } 140 | 141 | if (buf.remaining() > 0) { 142 | ByteBuffer finish = ByteBuffer.allocate(8).order( 143 | ByteOrder.LITTLE_ENDIAN); 144 | // for big-endian version, do this first: 145 | // finish.position(8-buf.remaining()); 146 | finish.put(buf).rewind(); 147 | h ^= finish.getLong(); 148 | h *= m; 149 | } 150 | 151 | h ^= h >>> r; 152 | h *= m; 153 | h ^= h >>> r; 154 | 155 | buf.order(byteOrder); 156 | return h; 157 | } 158 | 159 | public long hash(byte[] key) { 160 | return hash64A(key, 0x1234ABCD); 161 | } 162 | 163 | public long hash(String key) { 164 | return hash(SafeEncoder.encode(key)); 165 | } 166 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/JedisPoolTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests; 2 | 3 | import java.net.URI; 4 | import java.net.URISyntaxException; 5 | 6 | import org.apache.commons.pool.impl.GenericObjectPool; 7 | import org.apache.commons.pool.impl.GenericObjectPool.Config; 8 | import org.junit.Assert; 9 | import org.junit.Test; 10 | 11 | import redis.clients.jedis.BinaryJedis; 12 | import redis.clients.jedis.Jedis; 13 | import redis.clients.jedis.JedisPool; 14 | import redis.clients.jedis.JedisPoolConfig; 15 | import redis.clients.jedis.exceptions.JedisConnectionException; 16 | import redis.clients.jedis.tests.HostAndPortUtil.HostAndPort; 17 | 18 | public class JedisPoolTest extends Assert { 19 | private static HostAndPort hnp = HostAndPortUtil.getRedisServers().get(0); 20 | 21 | @Test 22 | public void checkConnections() { 23 | JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, 24 | hnp.port, 2000); 25 | Jedis jedis = pool.getResource(); 26 | jedis.auth("foobared"); 27 | jedis.set("foo", "bar"); 28 | assertEquals("bar", jedis.get("foo")); 29 | pool.returnResource(jedis); 30 | pool.destroy(); 31 | } 32 | 33 | @Test 34 | public void checkConnectionWithDefaultPort() { 35 | JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, 36 | hnp.port); 37 | Jedis jedis = pool.getResource(); 38 | jedis.auth("foobared"); 39 | jedis.set("foo", "bar"); 40 | assertEquals("bar", jedis.get("foo")); 41 | pool.returnResource(jedis); 42 | pool.destroy(); 43 | } 44 | 45 | @Test 46 | public void checkJedisIsReusedWhenReturned() { 47 | JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, 48 | hnp.port); 49 | Jedis jedis = pool.getResource(); 50 | jedis.auth("foobared"); 51 | jedis.set("foo", "0"); 52 | pool.returnResource(jedis); 53 | 54 | jedis = pool.getResource(); 55 | jedis.auth("foobared"); 56 | jedis.incr("foo"); 57 | pool.returnResource(jedis); 58 | pool.destroy(); 59 | } 60 | 61 | @Test 62 | public void checkPoolRepairedWhenJedisIsBroken() { 63 | JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, 64 | hnp.port); 65 | Jedis jedis = pool.getResource(); 66 | jedis.auth("foobared"); 67 | jedis.quit(); 68 | pool.returnBrokenResource(jedis); 69 | 70 | jedis = pool.getResource(); 71 | jedis.auth("foobared"); 72 | jedis.incr("foo"); 73 | pool.returnResource(jedis); 74 | pool.destroy(); 75 | } 76 | 77 | @Test(expected = JedisConnectionException.class) 78 | public void checkPoolOverflow() { 79 | Config config = new Config(); 80 | config.maxActive = 1; 81 | config.whenExhaustedAction = GenericObjectPool.WHEN_EXHAUSTED_FAIL; 82 | JedisPool pool = new JedisPool(config, hnp.host, hnp.port); 83 | Jedis jedis = pool.getResource(); 84 | jedis.auth("foobared"); 85 | jedis.set("foo", "0"); 86 | 87 | Jedis newJedis = pool.getResource(); 88 | newJedis.auth("foobared"); 89 | newJedis.incr("foo"); 90 | } 91 | 92 | @Test 93 | public void securePool() { 94 | JedisPoolConfig config = new JedisPoolConfig(); 95 | config.setTestOnBorrow(true); 96 | JedisPool pool = new JedisPool(config, hnp.host, hnp.port, 2000, "foobared"); 97 | Jedis jedis = pool.getResource(); 98 | jedis.set("foo", "bar"); 99 | pool.returnResource(jedis); 100 | pool.destroy(); 101 | } 102 | 103 | @Test 104 | public void nonDefaultDatabase() { 105 | JedisPool pool0 = new JedisPool(new JedisPoolConfig(), hnp.host, 106 | hnp.port, 2000, "foobared"); 107 | Jedis jedis0 = pool0.getResource(); 108 | jedis0.set("foo", "bar"); 109 | assertEquals( "bar", jedis0.get("foo") ); 110 | pool0.returnResource(jedis0); 111 | pool0.destroy(); 112 | 113 | JedisPool pool1 = new JedisPool(new JedisPoolConfig(), hnp.host, 114 | hnp.port, 2000, "foobared", 1); 115 | Jedis jedis1 = pool1.getResource(); 116 | assertNull( jedis1.get("foo") ); 117 | pool1.returnResource(jedis0); 118 | pool1.destroy(); 119 | } 120 | 121 | @Test 122 | public void returnBinary() { 123 | JedisPool pool = new JedisPool(new JedisPoolConfig(), hnp.host, 124 | hnp.port, 2000); 125 | BinaryJedis jedis = pool.getResource(); 126 | pool.returnResource(jedis); 127 | pool.destroy(); 128 | } 129 | 130 | @Test 131 | public void startWithUrlString() { 132 | Jedis j = new Jedis("localhost", 6380); 133 | j.auth("foobared"); 134 | j.select(2); 135 | j.set("foo", "bar"); 136 | JedisPool pool = new JedisPool("redis://:foobared@localhost:6380/2"); 137 | Jedis jedis = pool.getResource(); 138 | assertEquals("PONG", jedis.ping()); 139 | assertEquals("bar", jedis.get("foo")); 140 | } 141 | 142 | @Test 143 | public void startWithUrl() throws URISyntaxException { 144 | Jedis j = new Jedis("localhost", 6380); 145 | j.auth("foobared"); 146 | j.select(2); 147 | j.set("foo", "bar"); 148 | JedisPool pool = new JedisPool(new URI("redis://:foobared@localhost:6380/2")); 149 | Jedis jedis = pool.getResource(); 150 | assertEquals("PONG", jedis.ping()); 151 | assertEquals("bar", jedis.get("foo")); 152 | } 153 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/SortingParams.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import static redis.clients.jedis.Protocol.Keyword.ALPHA; 4 | import static redis.clients.jedis.Protocol.Keyword.ASC; 5 | import static redis.clients.jedis.Protocol.Keyword.BY; 6 | import static redis.clients.jedis.Protocol.Keyword.DESC; 7 | import static redis.clients.jedis.Protocol.Keyword.GET; 8 | import static redis.clients.jedis.Protocol.Keyword.LIMIT; 9 | import static redis.clients.jedis.Protocol.Keyword.NOSORT; 10 | 11 | import java.util.ArrayList; 12 | import java.util.Collection; 13 | import java.util.Collections; 14 | import java.util.List; 15 | 16 | import redis.clients.util.SafeEncoder; 17 | 18 | /** 19 | * Builder Class for {@link Jedis#sort(String, SortingParams) SORT} Parameters. 20 | * 21 | */ 22 | public class SortingParams { 23 | private List params = new ArrayList(); 24 | 25 | /** 26 | * Sort by weight in keys. 27 | *

28 | * Takes a pattern that is used in order to generate the key names of the 29 | * weights used for sorting. Weight key names are obtained substituting the 30 | * first occurrence of * with the actual value of the elements on the list. 31 | *

32 | * The pattern for a normal key/value pair is "keyname*" and for a value in 33 | * a hash "keyname*->fieldname". 34 | * 35 | * @param pattern 36 | * @return the SortingParams Object 37 | */ 38 | public SortingParams by(final String pattern) { 39 | return by(SafeEncoder.encode(pattern)); 40 | } 41 | 42 | /** 43 | * Sort by weight in keys. 44 | *

45 | * Takes a pattern that is used in order to generate the key names of the 46 | * weights used for sorting. Weight key names are obtained substituting the 47 | * first occurrence of * with the actual value of the elements on the list. 48 | *

49 | * The pattern for a normal key/value pair is "keyname*" and for a value in 50 | * a hash "keyname*->fieldname". 51 | * 52 | * @param pattern 53 | * @return the SortingParams Object 54 | */ 55 | public SortingParams by(final byte[] pattern) { 56 | params.add(BY.raw); 57 | params.add(pattern); 58 | return this; 59 | } 60 | 61 | /** 62 | * No sorting. 63 | *

64 | * This is useful if you want to retrieve a external key (using 65 | * {@link #get(String...) GET}) but you don't want the sorting overhead. 66 | * 67 | * @return the SortingParams Object 68 | */ 69 | public SortingParams nosort() { 70 | params.add(BY.raw); 71 | params.add(NOSORT.raw); 72 | return this; 73 | } 74 | 75 | public Collection getParams() { 76 | return Collections.unmodifiableCollection(params); 77 | } 78 | 79 | /** 80 | * Get the Sorting in Descending Order. 81 | * 82 | * @return the sortingParams Object 83 | */ 84 | public SortingParams desc() { 85 | params.add(DESC.raw); 86 | return this; 87 | } 88 | 89 | /** 90 | * Get the Sorting in Ascending Order. This is the default order. 91 | * 92 | * @return the SortingParams Object 93 | */ 94 | public SortingParams asc() { 95 | params.add(ASC.raw); 96 | return this; 97 | } 98 | 99 | /** 100 | * Limit the Numbers of returned Elements. 101 | * 102 | * @param start 103 | * is zero based 104 | * @param count 105 | * @return the SortingParams Object 106 | */ 107 | public SortingParams limit(final int start, final int count) { 108 | params.add(LIMIT.raw); 109 | params.add(Protocol.toByteArray(start)); 110 | params.add(Protocol.toByteArray(count)); 111 | return this; 112 | } 113 | 114 | /** 115 | * Sort lexicographicaly. Note that Redis is utf-8 aware assuming you set 116 | * the right value for the LC_COLLATE environment variable. 117 | * 118 | * @return the SortingParams Object 119 | */ 120 | public SortingParams alpha() { 121 | params.add(ALPHA.raw); 122 | return this; 123 | } 124 | 125 | /** 126 | * Retrieving external keys from the result of the search. 127 | *

128 | * Takes a pattern that is used in order to generate the key names of the 129 | * result of sorting. The key names are obtained substituting the first 130 | * occurrence of * with the actual value of the elements on the list. 131 | *

132 | * The pattern for a normal key/value pair is "keyname*" and for a value in 133 | * a hash "keyname*->fieldname". 134 | *

135 | * To get the list itself use the char # as pattern. 136 | * 137 | * @param patterns 138 | * @return the SortingParams Object 139 | */ 140 | public SortingParams get(String... patterns) { 141 | for (final String pattern : patterns) { 142 | params.add(GET.raw); 143 | params.add(SafeEncoder.encode(pattern)); 144 | } 145 | return this; 146 | } 147 | 148 | /** 149 | * Retrieving external keys from the result of the search. 150 | *

151 | * Takes a pattern that is used in order to generate the key names of the 152 | * result of sorting. The key names are obtained substituting the first 153 | * occurrence of * with the actual value of the elements on the list. 154 | *

155 | * The pattern for a normal key/value pair is "keyname*" and for a value in 156 | * a hash "keyname*->fieldname". 157 | *

158 | * To get the list itself use the char # as pattern. 159 | * 160 | * @param patterns 161 | * @return the SortingParams Object 162 | */ 163 | public SortingParams get(byte[]... patterns) { 164 | for (final byte[] pattern : patterns) { 165 | params.add(GET.raw); 166 | params.add(pattern); 167 | } 168 | return this; 169 | } 170 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/StringValuesCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.ArrayList; 4 | import java.util.List; 5 | 6 | import org.junit.Test; 7 | 8 | import redis.clients.jedis.exceptions.JedisDataException; 9 | 10 | public class StringValuesCommandsTest extends JedisCommandTestBase { 11 | @Test 12 | public void setAndGet() { 13 | String status = jedis.set("foo", "bar"); 14 | assertEquals("OK", status); 15 | 16 | String value = jedis.get("foo"); 17 | assertEquals("bar", value); 18 | 19 | assertEquals(null, jedis.get("bar")); 20 | } 21 | 22 | @Test 23 | public void getSet() { 24 | String value = jedis.getSet("foo", "bar"); 25 | assertEquals(null, value); 26 | value = jedis.get("foo"); 27 | assertEquals("bar", value); 28 | } 29 | 30 | @Test 31 | public void mget() { 32 | List values = jedis.mget("foo", "bar"); 33 | List expected = new ArrayList(); 34 | expected.add(null); 35 | expected.add(null); 36 | 37 | assertEquals(expected, values); 38 | 39 | jedis.set("foo", "bar"); 40 | 41 | expected = new ArrayList(); 42 | expected.add("bar"); 43 | expected.add(null); 44 | values = jedis.mget("foo", "bar"); 45 | 46 | assertEquals(expected, values); 47 | 48 | jedis.set("bar", "foo"); 49 | 50 | expected = new ArrayList(); 51 | expected.add("bar"); 52 | expected.add("foo"); 53 | values = jedis.mget("foo", "bar"); 54 | 55 | assertEquals(expected, values); 56 | } 57 | 58 | @Test 59 | public void setnx() { 60 | long status = jedis.setnx("foo", "bar"); 61 | assertEquals(1, status); 62 | assertEquals("bar", jedis.get("foo")); 63 | 64 | status = jedis.setnx("foo", "bar2"); 65 | assertEquals(0, status); 66 | assertEquals("bar", jedis.get("foo")); 67 | } 68 | 69 | @Test 70 | public void setex() { 71 | String status = jedis.setex("foo", 20, "bar"); 72 | assertEquals("OK", status); 73 | long ttl = jedis.ttl("foo"); 74 | assertTrue(ttl > 0 && ttl <= 20); 75 | } 76 | 77 | @Test 78 | public void mset() { 79 | String status = jedis.mset("foo", "bar", "bar", "foo"); 80 | assertEquals("OK", status); 81 | assertEquals("bar", jedis.get("foo")); 82 | assertEquals("foo", jedis.get("bar")); 83 | } 84 | 85 | @Test 86 | public void msetnx() { 87 | long status = jedis.msetnx("foo", "bar", "bar", "foo"); 88 | assertEquals(1, status); 89 | assertEquals("bar", jedis.get("foo")); 90 | assertEquals("foo", jedis.get("bar")); 91 | 92 | status = jedis.msetnx("foo", "bar1", "bar2", "foo2"); 93 | assertEquals(0, status); 94 | assertEquals("bar", jedis.get("foo")); 95 | assertEquals("foo", jedis.get("bar")); 96 | } 97 | 98 | @Test(expected = JedisDataException.class) 99 | public void incrWrongValue() { 100 | jedis.set("foo", "bar"); 101 | jedis.incr("foo"); 102 | } 103 | 104 | @Test 105 | public void incr() { 106 | long value = jedis.incr("foo"); 107 | assertEquals(1, value); 108 | value = jedis.incr("foo"); 109 | assertEquals(2, value); 110 | } 111 | 112 | @Test(expected = JedisDataException.class) 113 | public void incrByWrongValue() { 114 | jedis.set("foo", "bar"); 115 | jedis.incrBy("foo", 2); 116 | } 117 | 118 | @Test 119 | public void incrBy() { 120 | long value = jedis.incrBy("foo", 2); 121 | assertEquals(2, value); 122 | value = jedis.incrBy("foo", 2); 123 | assertEquals(4, value); 124 | } 125 | 126 | @Test(expected = JedisDataException.class) 127 | public void decrWrongValue() { 128 | jedis.set("foo", "bar"); 129 | jedis.decr("foo"); 130 | } 131 | 132 | @Test 133 | public void decr() { 134 | long value = jedis.decr("foo"); 135 | assertEquals(-1, value); 136 | value = jedis.decr("foo"); 137 | assertEquals(-2, value); 138 | } 139 | 140 | @Test(expected = JedisDataException.class) 141 | public void decrByWrongValue() { 142 | jedis.set("foo", "bar"); 143 | jedis.decrBy("foo", 2); 144 | } 145 | 146 | @Test 147 | public void decrBy() { 148 | long value = jedis.decrBy("foo", 2); 149 | assertEquals(-2, value); 150 | value = jedis.decrBy("foo", 2); 151 | assertEquals(-4, value); 152 | } 153 | 154 | @Test 155 | public void append() { 156 | long value = jedis.append("foo", "bar"); 157 | assertEquals(3, value); 158 | assertEquals("bar", jedis.get("foo")); 159 | value = jedis.append("foo", "bar"); 160 | assertEquals(6, value); 161 | assertEquals("barbar", jedis.get("foo")); 162 | } 163 | 164 | @Test 165 | public void substr() { 166 | jedis.set("s", "This is a string"); 167 | assertEquals("This", jedis.substr("s", 0, 3)); 168 | assertEquals("ing", jedis.substr("s", -3, -1)); 169 | assertEquals("This is a string", jedis.substr("s", 0, -1)); 170 | assertEquals(" string", jedis.substr("s", 9, 100000)); 171 | } 172 | 173 | @Test 174 | public void strlen() { 175 | jedis.set("s", "This is a string"); 176 | assertEquals("This is a string".length(), jedis.strlen("s").intValue()); 177 | } 178 | 179 | @Test 180 | public void incrLargeNumbers() { 181 | long value = jedis.incr("foo"); 182 | assertEquals(1, value); 183 | assertEquals(1L + Integer.MAX_VALUE, (long) jedis.incrBy("foo", 184 | Integer.MAX_VALUE)); 185 | } 186 | 187 | @Test(expected = JedisDataException.class) 188 | public void incrReallyLargeNumbers() { 189 | jedis.set("foo", Long.toString(Long.MAX_VALUE)); 190 | long value = jedis.incr("foo"); 191 | assertEquals(Long.MIN_VALUE, value); 192 | } 193 | } -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/VariadicCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.ArrayList; 4 | import java.util.HashMap; 5 | import java.util.LinkedHashSet; 6 | import java.util.List; 7 | import java.util.Map; 8 | import java.util.Set; 9 | 10 | import org.junit.Test; 11 | 12 | public class VariadicCommandsTest extends JedisCommandTestBase { 13 | final byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; 14 | final byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; 15 | final byte[] bcar = { 0x09, 0x0A, 0x0B, 0x0C }; 16 | final byte[] bfoo1 = { 0x01, 0x02, 0x03, 0x04, 0x0A }; 17 | final byte[] bfoo2 = { 0x01, 0x02, 0x03, 0x04, 0x0B }; 18 | 19 | @Test 20 | public void hdel() { 21 | Map hash = new HashMap(); 22 | hash.put("bar", "car"); 23 | hash.put("car", "bar"); 24 | hash.put("foo2", "bar"); 25 | jedis.hmset("foo", hash); 26 | 27 | assertEquals(0, jedis.hdel("bar", "foo", "foo1").intValue()); 28 | assertEquals(0, jedis.hdel("foo", "foo", "foo1").intValue()); 29 | assertEquals(2, jedis.hdel("foo", "bar", "foo2").intValue()); 30 | assertEquals(null, jedis.hget("foo", "bar")); 31 | 32 | // Binary 33 | Map bhash = new HashMap(); 34 | bhash.put(bbar, bcar); 35 | bhash.put(bcar, bbar); 36 | bhash.put(bfoo2, bbar); 37 | jedis.hmset(bfoo, bhash); 38 | 39 | assertEquals(0, jedis.hdel(bbar, bfoo, bfoo1).intValue()); 40 | assertEquals(0, jedis.hdel(bfoo, bfoo, bfoo1).intValue()); 41 | assertEquals(2, jedis.hdel(bfoo, bbar, bfoo2).intValue()); 42 | assertEquals(null, jedis.hget(bfoo, bbar)); 43 | 44 | } 45 | 46 | @Test 47 | public void rpush() { 48 | long size = jedis.rpush("foo", "bar", "foo"); 49 | assertEquals(2, size); 50 | 51 | List expected = new ArrayList(); 52 | expected.add("bar"); 53 | expected.add("foo"); 54 | 55 | List values = jedis.lrange("foo",0,-1); 56 | assertEquals(expected, values); 57 | 58 | // Binary 59 | size = jedis.rpush(bfoo, bbar, bfoo); 60 | assertEquals(2, size); 61 | 62 | List bexpected = new ArrayList(); 63 | bexpected.add(bbar); 64 | bexpected.add(bfoo); 65 | 66 | List bvalues = jedis.lrange(bfoo, 0, -1); 67 | assertEquals(bexpected, bvalues); 68 | 69 | } 70 | 71 | @Test 72 | public void lpush() { 73 | long size = jedis.lpush("foo", "bar", "foo"); 74 | assertEquals(2, size); 75 | 76 | List expected = new ArrayList(); 77 | expected.add("foo"); 78 | expected.add("bar"); 79 | 80 | List values = jedis.lrange("foo",0,-1); 81 | assertEquals(expected, values); 82 | 83 | // Binary 84 | size = jedis.lpush(bfoo, bbar, bfoo); 85 | assertEquals(2, size); 86 | 87 | List bexpected = new ArrayList(); 88 | bexpected.add(bfoo); 89 | bexpected.add(bbar); 90 | 91 | List bvalues = jedis.lrange(bfoo, 0, -1); 92 | assertEquals(bexpected, bvalues); 93 | 94 | } 95 | 96 | @Test 97 | public void sadd() { 98 | long status = jedis.sadd("foo", "bar", "foo1"); 99 | assertEquals(2, status); 100 | 101 | status = jedis.sadd("foo", "bar", "car"); 102 | assertEquals(1, status); 103 | 104 | status = jedis.sadd("foo", "bar", "foo1"); 105 | assertEquals(0, status); 106 | 107 | status = jedis.sadd(bfoo, bbar, bfoo1); 108 | assertEquals(2, status); 109 | 110 | status = jedis.sadd(bfoo, bbar, bcar); 111 | assertEquals(1, status); 112 | 113 | status = jedis.sadd(bfoo, bbar, bfoo1); 114 | assertEquals(0, status); 115 | 116 | } 117 | 118 | @Test 119 | public void zadd() { 120 | Map scoreMembers = new HashMap(); 121 | scoreMembers.put(1d, "bar"); 122 | scoreMembers.put(10d, "foo"); 123 | 124 | long status = jedis.zadd("foo", scoreMembers); 125 | assertEquals(2, status); 126 | 127 | scoreMembers.clear(); 128 | scoreMembers.put(0.1d, "car"); 129 | scoreMembers.put(2d, "bar"); 130 | 131 | status = jedis.zadd("foo", scoreMembers); 132 | assertEquals(1, status); 133 | 134 | Map bscoreMembers = new HashMap(); 135 | bscoreMembers.put(1d, bbar); 136 | bscoreMembers.put(10d, bfoo); 137 | 138 | status = jedis.zadd(bfoo, bscoreMembers); 139 | assertEquals(2, status); 140 | 141 | bscoreMembers.clear(); 142 | bscoreMembers.put(0.1d, bcar); 143 | bscoreMembers.put(2d, bbar); 144 | 145 | status = jedis.zadd(bfoo, bscoreMembers); 146 | assertEquals(1, status); 147 | 148 | } 149 | 150 | @Test 151 | public void zrem() { 152 | jedis.zadd("foo", 1d, "bar"); 153 | jedis.zadd("foo", 2d, "car"); 154 | jedis.zadd("foo", 3d, "foo1"); 155 | 156 | long status = jedis.zrem("foo", "bar", "car"); 157 | 158 | Set expected = new LinkedHashSet(); 159 | expected.add("foo1"); 160 | 161 | assertEquals(2, status); 162 | assertEquals(expected, jedis.zrange("foo", 0, 100)); 163 | 164 | status = jedis.zrem("foo", "bar", "car"); 165 | assertEquals(0, status); 166 | 167 | status = jedis.zrem("foo", "bar", "foo1"); 168 | assertEquals(1, status); 169 | 170 | //Binary 171 | jedis.zadd(bfoo, 1d, bbar); 172 | jedis.zadd(bfoo, 2d, bcar); 173 | jedis.zadd(bfoo, 3d, bfoo1); 174 | 175 | status = jedis.zrem(bfoo, bbar, bcar); 176 | 177 | Set bexpected = new LinkedHashSet(); 178 | bexpected.add(bfoo); 179 | 180 | assertEquals(2, status); 181 | assertEquals(bexpected, jedis.zrange(bfoo, 0, 100)); 182 | 183 | status = jedis.zrem(bfoo, bbar, bcar); 184 | assertEquals(0, status); 185 | 186 | status = jedis.zrem(bfoo, bbar, bfoo1); 187 | assertEquals(1, status); 188 | 189 | } 190 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisPubSub.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import static redis.clients.jedis.Protocol.Keyword.MESSAGE; 4 | import static redis.clients.jedis.Protocol.Keyword.PMESSAGE; 5 | import static redis.clients.jedis.Protocol.Keyword.PSUBSCRIBE; 6 | import static redis.clients.jedis.Protocol.Keyword.PUNSUBSCRIBE; 7 | import static redis.clients.jedis.Protocol.Keyword.SUBSCRIBE; 8 | import static redis.clients.jedis.Protocol.Keyword.UNSUBSCRIBE; 9 | 10 | import java.util.Arrays; 11 | import java.util.List; 12 | 13 | import redis.clients.jedis.exceptions.JedisConnectionException; 14 | import redis.clients.jedis.exceptions.JedisException; 15 | import redis.clients.util.SafeEncoder; 16 | 17 | public abstract class JedisPubSub { 18 | private int subscribedChannels = 0; 19 | private Client client; 20 | 21 | public abstract void onMessage(String channel, String message); 22 | 23 | public abstract void onPMessage(String pattern, String channel, 24 | String message); 25 | 26 | public abstract void onSubscribe(String channel, int subscribedChannels); 27 | 28 | public abstract void onUnsubscribe(String channel, int subscribedChannels); 29 | 30 | public abstract void onPUnsubscribe(String pattern, int subscribedChannels); 31 | 32 | public abstract void onPSubscribe(String pattern, int subscribedChannels); 33 | 34 | public void unsubscribe() { 35 | if (client == null) { 36 | throw new JedisConnectionException( 37 | "JedisPubSub was not subscribed to a Jedis instance."); 38 | } 39 | client.unsubscribe(); 40 | client.flush(); 41 | } 42 | 43 | public void unsubscribe(String... channels) { 44 | client.unsubscribe(channels); 45 | client.flush(); 46 | } 47 | 48 | public void subscribe(String... channels) { 49 | client.subscribe(channels); 50 | client.flush(); 51 | } 52 | 53 | public void psubscribe(String... patterns) { 54 | client.psubscribe(patterns); 55 | client.flush(); 56 | } 57 | 58 | public void punsubscribe() { 59 | client.punsubscribe(); 60 | client.flush(); 61 | } 62 | 63 | public void punsubscribe(String... patterns) { 64 | client.punsubscribe(patterns); 65 | client.flush(); 66 | } 67 | 68 | public boolean isSubscribed() { 69 | return subscribedChannels > 0; 70 | } 71 | 72 | public void proceedWithPatterns(Client client, String... patterns) { 73 | this.client = client; 74 | client.psubscribe(patterns); 75 | client.flush(); 76 | process(client); 77 | } 78 | 79 | public void proceed(Client client, String... channels) { 80 | this.client = client; 81 | client.subscribe(channels); 82 | client.flush(); 83 | process(client); 84 | } 85 | 86 | private void process(Client client) { 87 | do { 88 | List reply = client.getObjectMultiBulkReply(); 89 | final Object firstObj = reply.get(0); 90 | if (!(firstObj instanceof byte[])) { 91 | throw new JedisException("Unknown message type: " + firstObj); 92 | } 93 | final byte[] resp = (byte[]) firstObj; 94 | if (Arrays.equals(SUBSCRIBE.raw, resp)) { 95 | subscribedChannels = ((Long) reply.get(2)).intValue(); 96 | final byte[] bchannel = (byte[]) reply.get(1); 97 | final String strchannel = (bchannel == null) ? null 98 | : SafeEncoder.encode(bchannel); 99 | onSubscribe(strchannel, subscribedChannels); 100 | } else if (Arrays.equals(UNSUBSCRIBE.raw, resp)) { 101 | subscribedChannels = ((Long) reply.get(2)).intValue(); 102 | final byte[] bchannel = (byte[]) reply.get(1); 103 | final String strchannel = (bchannel == null) ? null 104 | : SafeEncoder.encode(bchannel); 105 | onUnsubscribe(strchannel, subscribedChannels); 106 | } else if (Arrays.equals(MESSAGE.raw, resp)) { 107 | final byte[] bchannel = (byte[]) reply.get(1); 108 | final byte[] bmesg = (byte[]) reply.get(2); 109 | final String strchannel = (bchannel == null) ? null 110 | : SafeEncoder.encode(bchannel); 111 | final String strmesg = (bmesg == null) ? null : SafeEncoder 112 | .encode(bmesg); 113 | onMessage(strchannel, strmesg); 114 | } else if (Arrays.equals(PMESSAGE.raw, resp)) { 115 | final byte[] bpattern = (byte[]) reply.get(1); 116 | final byte[] bchannel = (byte[]) reply.get(2); 117 | final byte[] bmesg = (byte[]) reply.get(3); 118 | final String strpattern = (bpattern == null) ? null 119 | : SafeEncoder.encode(bpattern); 120 | final String strchannel = (bchannel == null) ? null 121 | : SafeEncoder.encode(bchannel); 122 | final String strmesg = (bmesg == null) ? null : SafeEncoder 123 | .encode(bmesg); 124 | onPMessage(strpattern, strchannel, strmesg); 125 | } else if (Arrays.equals(PSUBSCRIBE.raw, resp)) { 126 | subscribedChannels = ((Long) reply.get(2)).intValue(); 127 | final byte[] bpattern = (byte[]) reply.get(1); 128 | final String strpattern = (bpattern == null) ? null 129 | : SafeEncoder.encode(bpattern); 130 | onPSubscribe(strpattern, subscribedChannels); 131 | } else if (Arrays.equals(PUNSUBSCRIBE.raw, resp)) { 132 | subscribedChannels = ((Long) reply.get(2)).intValue(); 133 | final byte[] bpattern = (byte[]) reply.get(1); 134 | final String strpattern = (bpattern == null) ? null 135 | : SafeEncoder.encode(bpattern); 136 | onPUnsubscribe(strpattern, subscribedChannels); 137 | } else { 138 | throw new JedisException("Unknown message type: " + firstObj); 139 | } 140 | } while (isSubscribed()); 141 | } 142 | 143 | public int getSubscribedChannels() { 144 | return subscribedChannels; 145 | } 146 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/JedisCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | /** 8 | * Common interface for sharded and non-sharded Jedis 9 | */ 10 | public interface JedisCommands { 11 | String set(String key, String value); 12 | 13 | String get(String key); 14 | 15 | Boolean exists(String key); 16 | 17 | Long persist(String key); 18 | 19 | String type(String key); 20 | 21 | Long expire(String key, int seconds); 22 | 23 | Long expireAt(String key, long unixTime); 24 | 25 | Long ttl(String key); 26 | 27 | Boolean setbit(String key, long offset, boolean value); 28 | 29 | Boolean setbit(String key, long offset, String value); 30 | 31 | Boolean getbit(String key, long offset); 32 | 33 | Long setrange(String key, long offset, String value); 34 | 35 | String getrange(String key, long startOffset, long endOffset); 36 | 37 | String getSet(String key, String value); 38 | 39 | Long setnx(String key, String value); 40 | 41 | String setex(String key, int seconds, String value); 42 | 43 | Long decrBy(String key, long integer); 44 | 45 | Long decr(String key); 46 | 47 | Long incrBy(String key, long integer); 48 | 49 | Long incr(String key); 50 | 51 | Long append(String key, String value); 52 | 53 | String substr(String key, int start, int end); 54 | 55 | Long hset(String key, String field, String value); 56 | 57 | String hget(String key, String field); 58 | 59 | Long hsetnx(String key, String field, String value); 60 | 61 | String hmset(String key, Map hash); 62 | 63 | List hmget(String key, String... fields); 64 | 65 | Long hincrBy(String key, String field, long value); 66 | 67 | Boolean hexists(String key, String field); 68 | 69 | Long hdel(String key, String... field); 70 | 71 | Long hlen(String key); 72 | 73 | Set hkeys(String key); 74 | 75 | List hvals(String key); 76 | 77 | Map hgetAll(String key); 78 | 79 | Long rpush(String key, String... string); 80 | 81 | Long lpush(String key, String... string); 82 | 83 | Long llen(String key); 84 | 85 | List lrange(String key, long start, long end); 86 | 87 | String ltrim(String key, long start, long end); 88 | 89 | String lindex(String key, long index); 90 | 91 | String lset(String key, long index, String value); 92 | 93 | Long lrem(String key, long count, String value); 94 | 95 | String lpop(String key); 96 | 97 | String rpop(String key); 98 | 99 | Long sadd(String key, String... member); 100 | 101 | Set smembers(String key); 102 | 103 | Long srem(String key, String... member); 104 | 105 | String spop(String key); 106 | 107 | Long scard(String key); 108 | 109 | Boolean sismember(String key, String member); 110 | 111 | String srandmember(String key); 112 | 113 | Long strlen(String key); 114 | 115 | Long zadd(String key, double score, String member); 116 | 117 | Long zadd(String key, Map scoreMembers); 118 | 119 | Set zrange(String key, long start, long end); 120 | 121 | Long zrem(String key, String... member); 122 | 123 | Double zincrby(String key, double score, String member); 124 | 125 | Long zrank(String key, String member); 126 | 127 | Long zrevrank(String key, String member); 128 | 129 | Set zrevrange(String key, long start, long end); 130 | 131 | Set zrangeWithScores(String key, long start, long end); 132 | 133 | Set zrevrangeWithScores(String key, long start, long end); 134 | 135 | Long zcard(String key); 136 | 137 | Double zscore(String key, String member); 138 | 139 | List sort(String key); 140 | 141 | List sort(String key, SortingParams sortingParameters); 142 | 143 | Long zcount(String key, double min, double max); 144 | 145 | Long zcount(String key, String min, String max); 146 | 147 | Set zrangeByScore(String key, double min, double max); 148 | 149 | Set zrangeByScore(String key, String min, String max); 150 | 151 | Set zrevrangeByScore(String key, double max, double min); 152 | 153 | Set zrangeByScore(String key, double min, double max, int offset, 154 | int count); 155 | 156 | Set zrevrangeByScore(String key, String max, String min); 157 | 158 | Set zrangeByScore(String key, String min, String max, int offset, 159 | int count); 160 | 161 | Set zrevrangeByScore(String key, double max, double min, 162 | int offset, int count); 163 | 164 | Set zrangeByScoreWithScores(String key, double min, double max); 165 | 166 | Set zrevrangeByScoreWithScores(String key, double max, double min); 167 | 168 | Set zrangeByScoreWithScores(String key, double min, double max, 169 | int offset, int count); 170 | 171 | Set zrevrangeByScore(String key, String max, String min, 172 | int offset, int count); 173 | 174 | Set zrangeByScoreWithScores(String key, String min, String max); 175 | 176 | Set zrevrangeByScoreWithScores(String key, String max, String min); 177 | 178 | Set zrangeByScoreWithScores(String key, String min, String max, 179 | int offset, int count); 180 | 181 | Set zrevrangeByScoreWithScores(String key, double max, double min, 182 | int offset, int count); 183 | 184 | Set zrevrangeByScoreWithScores(String key, String max, String min, 185 | int offset, int count); 186 | 187 | Long zremrangeByRank(String key, long start, long end); 188 | 189 | Long zremrangeByScore(String key, double start, double end); 190 | 191 | Long zremrangeByScore(String key, String start, String end); 192 | 193 | Long linsert(String key, Client.LIST_POSITION where, String pivot, 194 | String value); 195 | 196 | Long lpushx(String key, String... string); 197 | 198 | Long rpushx(String key, String... string); 199 | 200 | List blpop(String arg); 201 | 202 | List brpop(String arg); 203 | 204 | Long del(String key); 205 | 206 | String echo(String string); 207 | 208 | Long move(String key, int dbIndex); 209 | 210 | Long bitcount(final String key); 211 | 212 | Long bitcount(final String key, long start, long end); 213 | } 214 | -------------------------------------------------------------------------------- /gradlew: -------------------------------------------------------------------------------- 1 | #!/bin/bash 2 | 3 | ############################################################################## 4 | ## ## 5 | ## Gradle wrapper script for UN*X ## 6 | ## ## 7 | ############################################################################## 8 | 9 | # Uncomment those lines to set JVM options. GRADLE_OPTS and JAVA_OPTS can be used together. 10 | # GRADLE_OPTS="$GRADLE_OPTS -Xmx512m" 11 | # JAVA_OPTS="$JAVA_OPTS -Xmx512m" 12 | 13 | GRADLE_APP_NAME=Gradle 14 | 15 | # Use the maximum available, or set MAX_FD != -1 to use that value. 16 | MAX_FD="maximum" 17 | 18 | warn ( ) { 19 | echo "$*" 20 | } 21 | 22 | die ( ) { 23 | echo 24 | echo "$*" 25 | echo 26 | exit 1 27 | } 28 | 29 | # OS specific support (must be 'true' or 'false'). 30 | cygwin=false 31 | msys=false 32 | darwin=false 33 | case "`uname`" in 34 | CYGWIN* ) 35 | cygwin=true 36 | ;; 37 | Darwin* ) 38 | darwin=true 39 | ;; 40 | MINGW* ) 41 | msys=true 42 | ;; 43 | esac 44 | 45 | # Attempt to set JAVA_HOME if it's not already set. 46 | if [ -z "$JAVA_HOME" ] ; then 47 | if $darwin ; then 48 | [ -z "$JAVA_HOME" -a -d "/Library/Java/Home" ] && export JAVA_HOME="/Library/Java/Home" 49 | [ -z "$JAVA_HOME" -a -d "/System/Library/Frameworks/JavaVM.framework/Home" ] && export JAVA_HOME="/System/Library/Frameworks/JavaVM.framework/Home" 50 | else 51 | javaExecutable="`which javac`" 52 | [ -z "$javaExecutable" -o "`expr \"$javaExecutable\" : '\([^ ]*\)'`" = "no" ] && die "JAVA_HOME not set and cannot find javac to deduce location, please set JAVA_HOME." 53 | # readlink(1) is not available as standard on Solaris 10. 54 | readLink=`which readlink` 55 | [ `expr "$readLink" : '\([^ ]*\)'` = "no" ] && die "JAVA_HOME not set and readlink not available, please set JAVA_HOME." 56 | javaExecutable="`readlink -f \"$javaExecutable\"`" 57 | javaHome="`dirname \"$javaExecutable\"`" 58 | javaHome=`expr "$javaHome" : '\(.*\)/bin'` 59 | export JAVA_HOME="$javaHome" 60 | fi 61 | fi 62 | 63 | # For Cygwin, ensure paths are in UNIX format before anything is touched. 64 | if $cygwin ; then 65 | [ -n "$JAVACMD" ] && JAVACMD=`cygpath --unix "$JAVACMD"` 66 | [ -n "$JAVA_HOME" ] && JAVA_HOME=`cygpath --unix "$JAVA_HOME"` 67 | fi 68 | 69 | STARTER_MAIN_CLASS=org.gradle.wrapper.GradleWrapperMain 70 | CLASSPATH=`dirname "$0"`/gradle/wrapper/gradle-wrapper.jar 71 | WRAPPER_PROPERTIES=`dirname "$0"`/gradle/wrapper/gradle-wrapper.properties 72 | # Determine the Java command to use to start the JVM. 73 | if [ -z "$JAVACMD" ] ; then 74 | if [ -n "$JAVA_HOME" ] ; then 75 | if [ -x "$JAVA_HOME/jre/sh/java" ] ; then 76 | # IBM's JDK on AIX uses strange locations for the executables 77 | JAVACMD="$JAVA_HOME/jre/sh/java" 78 | else 79 | JAVACMD="$JAVA_HOME/bin/java" 80 | fi 81 | else 82 | JAVACMD="java" 83 | fi 84 | fi 85 | if [ ! -x "$JAVACMD" ] ; then 86 | die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME 87 | 88 | Please set the JAVA_HOME variable in your environment to match the 89 | location of your Java installation." 90 | fi 91 | if [ -z "$JAVA_HOME" ] ; then 92 | warn "JAVA_HOME environment variable is not set" 93 | fi 94 | 95 | # Increase the maximum file descriptors if we can. 96 | if [ "$cygwin" = "false" -a "$darwin" = "false" ] ; then 97 | MAX_FD_LIMIT=`ulimit -H -n` 98 | if [ $? -eq 0 ] ; then 99 | if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then 100 | MAX_FD="$MAX_FD_LIMIT" 101 | fi 102 | ulimit -n $MAX_FD 103 | if [ $? -ne 0 ] ; then 104 | warn "Could not set maximum file descriptor limit: $MAX_FD" 105 | fi 106 | else 107 | warn "Could not query businessSystem maximum file descriptor limit: $MAX_FD_LIMIT" 108 | fi 109 | fi 110 | 111 | # For Darwin, add GRADLE_APP_NAME to the JAVA_OPTS as -Xdock:name 112 | if $darwin; then 113 | JAVA_OPTS="$JAVA_OPTS -Xdock:name=$GRADLE_APP_NAME" 114 | # we may also want to set -Xdock:image 115 | fi 116 | 117 | # For Cygwin, switch paths to Windows format before running java 118 | if $cygwin ; then 119 | JAVA_HOME=`cygpath --path --mixed "$JAVA_HOME"` 120 | CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` 121 | 122 | # We build the pattern for arguments to be converted via cygpath 123 | ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null` 124 | SEP="" 125 | for dir in $ROOTDIRSRAW ; do 126 | ROOTDIRS="$ROOTDIRS$SEP$dir" 127 | SEP="|" 128 | done 129 | OURCYGPATTERN="(^($ROOTDIRS))" 130 | # Add a user-defined pattern to the cygpath arguments 131 | if [ "$GRADLE_CYGPATTERN" != "" ] ; then 132 | OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)" 133 | fi 134 | # Now convert the arguments - kludge to limit ourselves to /bin/sh 135 | i=0 136 | for arg in "$@" ; do 137 | CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -` 138 | CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option 139 | 140 | if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition 141 | eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"` 142 | else 143 | eval `echo args$i`="\"$arg\"" 144 | fi 145 | i=$((i+1)) 146 | done 147 | case $i in 148 | (0) set -- ;; 149 | (1) set -- "$args0" ;; 150 | (2) set -- "$args0" "$args1" ;; 151 | (3) set -- "$args0" "$args1" "$args2" ;; 152 | (4) set -- "$args0" "$args1" "$args2" "$args3" ;; 153 | (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; 154 | (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; 155 | (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; 156 | (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; 157 | (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; 158 | esac 159 | fi 160 | 161 | GRADLE_APP_BASE_NAME=`basename "$0"` 162 | 163 | exec "$JAVACMD" $JAVA_OPTS $GRADLE_OPTS \ 164 | -classpath "$CLASSPATH" \ 165 | -Dorg.gradle.appname="$GRADLE_APP_BASE_NAME" \ 166 | -Dorg.gradle.wrapper.properties="$WRAPPER_PROPERTIES" \ 167 | $STARTER_MAIN_CLASS \ 168 | "$@" 169 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/BinaryJedisCommands.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.Collection; 4 | import java.util.List; 5 | import java.util.Map; 6 | import java.util.Set; 7 | 8 | import redis.clients.jedis.BinaryClient.LIST_POSITION; 9 | 10 | /** 11 | * Common interface for sharded and non-sharded BinaryJedis 12 | */ 13 | public interface BinaryJedisCommands { 14 | String set(byte[] key, byte[] value); 15 | 16 | byte[] get(byte[] key); 17 | 18 | Boolean exists(byte[] key); 19 | 20 | Long persist(byte[] key); 21 | 22 | String type(byte[] key); 23 | 24 | Long expire(byte[] key, int seconds); 25 | 26 | Long expireAt(byte[] key, long unixTime); 27 | 28 | Long ttl(byte[] key); 29 | 30 | Boolean setbit(byte[] key, long offset, boolean value); 31 | 32 | Boolean setbit(byte[] key, long offset, byte[] value); 33 | 34 | Boolean getbit(byte[] key, long offset); 35 | 36 | Long setrange(byte[] key, long offset, byte[] value); 37 | 38 | byte[] getrange(byte[] key, long startOffset, long endOffset); 39 | 40 | byte[] getSet(byte[] key, byte[] value); 41 | 42 | Long setnx(byte[] key, byte[] value); 43 | 44 | String setex(byte[] key, int seconds, byte[] value); 45 | 46 | Long decrBy(byte[] key, long integer); 47 | 48 | Long decr(byte[] key); 49 | 50 | Long incrBy(byte[] key, long integer); 51 | 52 | Long incr(byte[] key); 53 | 54 | Long append(byte[] key, byte[] value); 55 | 56 | byte[] substr(byte[] key, int start, int end); 57 | 58 | Long hset(byte[] key, byte[] field, byte[] value); 59 | 60 | byte[] hget(byte[] key, byte[] field); 61 | 62 | Long hsetnx(byte[] key, byte[] field, byte[] value); 63 | 64 | String hmset(byte[] key, Map hash); 65 | 66 | List hmget(byte[] key, byte[]... fields); 67 | 68 | Long hincrBy(byte[] key, byte[] field, long value); 69 | 70 | Boolean hexists(byte[] key, byte[] field); 71 | 72 | Long hdel(byte[] key, byte[]... field); 73 | 74 | Long hlen(byte[] key); 75 | 76 | Set hkeys(byte[] key); 77 | 78 | Collection hvals(byte[] key); 79 | 80 | Map hgetAll(byte[] key); 81 | 82 | Long rpush(byte[] key, byte[]... args); 83 | 84 | Long lpush(byte[] key, byte[]... args); 85 | 86 | Long llen(byte[] key); 87 | 88 | List lrange(byte[] key, long start, long end); 89 | 90 | String ltrim(byte[] key, long start, long end); 91 | 92 | byte[] lindex(byte[] key, long index); 93 | 94 | String lset(byte[] key, long index, byte[] value); 95 | 96 | Long lrem(byte[] key, long count, byte[] value); 97 | 98 | byte[] lpop(byte[] key); 99 | 100 | byte[] rpop(byte[] key); 101 | 102 | Long sadd(byte[] key, byte[]... member); 103 | 104 | Set smembers(byte[] key); 105 | 106 | Long srem(byte[] key, byte[]... member); 107 | 108 | byte[] spop(byte[] key); 109 | 110 | Long scard(byte[] key); 111 | 112 | Boolean sismember(byte[] key, byte[] member); 113 | 114 | byte[] srandmember(byte[] key); 115 | 116 | Long strlen(byte[] key); 117 | 118 | Long zadd(byte[] key, double score, byte[] member); 119 | 120 | Long zadd(byte[] key, Map scoreMembers); 121 | 122 | Set zrange(byte[] key, long start, long end); 123 | 124 | Long zrem(byte[] key, byte[]... member); 125 | 126 | Double zincrby(byte[] key, double score, byte[] member); 127 | 128 | Long zrank(byte[] key, byte[] member); 129 | 130 | Long zrevrank(byte[] key, byte[] member); 131 | 132 | Set zrevrange(byte[] key, long start, long end); 133 | 134 | Set zrangeWithScores(byte[] key, long start, long end); 135 | 136 | Set zrevrangeWithScores(byte[] key, long start, long end); 137 | 138 | Long zcard(byte[] key); 139 | 140 | Double zscore(byte[] key, byte[] member); 141 | 142 | List sort(byte[] key); 143 | 144 | List sort(byte[] key, SortingParams sortingParameters); 145 | 146 | Long zcount(byte[] key, double min, double max); 147 | 148 | Long zcount(byte[] key, byte[] min, byte[] max); 149 | 150 | Set zrangeByScore(byte[] key, double min, double max); 151 | 152 | Set zrangeByScore(byte[] key, byte[] min, byte[] max); 153 | 154 | Set zrevrangeByScore(byte[] key, double max, double min); 155 | 156 | Set zrangeByScore(byte[] key, double min, double max, int offset, 157 | int count); 158 | 159 | Set zrevrangeByScore(byte[] key, byte[] max, byte[] min); 160 | 161 | Set zrangeByScore(byte[] key, byte[] min, byte[] max, int offset, 162 | int count); 163 | 164 | Set zrevrangeByScore(byte[] key, double max, double min, 165 | int offset, int count); 166 | 167 | Set zrangeByScoreWithScores(byte[] key, double min, double max); 168 | 169 | Set zrevrangeByScoreWithScores(byte[] key, double max, double min); 170 | 171 | Set zrangeByScoreWithScores(byte[] key, double min, double max, 172 | int offset, int count); 173 | 174 | Set zrevrangeByScore(byte[] key, byte[] max, byte[] min, 175 | int offset, int count); 176 | 177 | Set zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max); 178 | 179 | Set zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min); 180 | 181 | Set zrangeByScoreWithScores(byte[] key, byte[] min, byte[] max, 182 | int offset, int count); 183 | 184 | Set zrevrangeByScoreWithScores(byte[] key, double max, double min, 185 | int offset, int count); 186 | 187 | Set zrevrangeByScoreWithScores(byte[] key, byte[] max, byte[] min, 188 | int offset, int count); 189 | 190 | Long zremrangeByRank(byte[] key, long start, long end); 191 | 192 | Long zremrangeByScore(byte[] key, double start, double end); 193 | 194 | Long zremrangeByScore(byte[] key, byte[] start, byte[] end); 195 | 196 | Long linsert(byte[] key, Client.LIST_POSITION where, byte[] pivot, 197 | byte[] value); 198 | 199 | Long lpushx(byte[] key, byte[]... arg); 200 | 201 | Long rpushx(byte[] key, byte[]... arg); 202 | 203 | List blpop(byte[] arg); 204 | 205 | List brpop(byte[] arg); 206 | 207 | Long del(byte[] key); 208 | 209 | byte[] echo(byte[] arg); 210 | 211 | Long move(byte[] key, int dbIndex); 212 | 213 | Long bitcount(final byte[] key); 214 | 215 | Long bitcount(final byte[] key, long start, long end); 216 | } 217 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Protocol.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.io.IOException; 4 | import java.util.ArrayList; 5 | import java.util.List; 6 | 7 | import redis.clients.jedis.exceptions.JedisConnectionException; 8 | import redis.clients.jedis.exceptions.JedisDataException; 9 | import redis.clients.util.RedisInputStream; 10 | import redis.clients.util.RedisOutputStream; 11 | import redis.clients.util.SafeEncoder; 12 | 13 | public final class Protocol { 14 | 15 | public static final int DEFAULT_PORT = 6379; 16 | public static final int DEFAULT_TIMEOUT = 2000; 17 | public static final int DEFAULT_DATABASE = 0; 18 | 19 | public static final String CHARSET = "UTF-8"; 20 | 21 | public static final byte DOLLAR_BYTE = '$'; 22 | public static final byte ASTERISK_BYTE = '*'; 23 | public static final byte PLUS_BYTE = '+'; 24 | public static final byte MINUS_BYTE = '-'; 25 | public static final byte COLON_BYTE = ':'; 26 | 27 | public static final String SENTINEL_MASTERS = "masters"; 28 | public static final String SENTINEL_GET_MASTER_ADDR_BY_NAME = "get-master-addr-by-name"; 29 | public static final String SENTINEL_RESET = "reset"; 30 | public static final String SENTINEL_SLAVES = "slaves"; 31 | public static final String SENTINEL_IS_MASTER_DOWN_BY_ADDR = "is-master-down-by-addr"; 32 | 33 | private Protocol() { 34 | // this prevent the class from instantiation 35 | } 36 | 37 | public static void sendCommand(final RedisOutputStream os, 38 | final Command command, final byte[]... args) { 39 | sendCommand(os, command.raw, args); 40 | } 41 | 42 | private static void sendCommand(final RedisOutputStream os, 43 | final byte[] command, final byte[]... args) { 44 | try { 45 | os.write(ASTERISK_BYTE); 46 | os.writeIntCrLf(args.length + 1); 47 | os.write(DOLLAR_BYTE); 48 | os.writeIntCrLf(command.length); 49 | os.write(command); 50 | os.writeCrLf(); 51 | 52 | for (final byte[] arg : args) { 53 | os.write(DOLLAR_BYTE); 54 | os.writeIntCrLf(arg.length); 55 | os.write(arg); 56 | os.writeCrLf(); 57 | } 58 | } catch (IOException e) { 59 | throw new JedisConnectionException(e); 60 | } 61 | } 62 | 63 | private static void processError(final RedisInputStream is) { 64 | String message = is.readLine(); 65 | throw new JedisDataException(message); 66 | } 67 | 68 | private static Object process(final RedisInputStream is) { 69 | try { 70 | byte b = is.readByte(); 71 | if (b == MINUS_BYTE) { 72 | processError(is); 73 | } else if (b == ASTERISK_BYTE) { 74 | return processMultiBulkReply(is); 75 | } else if (b == COLON_BYTE) { 76 | return processInteger(is); 77 | } else if (b == DOLLAR_BYTE) { 78 | return processBulkReply(is); 79 | } else if (b == PLUS_BYTE) { 80 | return processStatusCodeReply(is); 81 | } else { 82 | throw new JedisConnectionException("Unknown reply: " + (char) b); 83 | } 84 | } catch (IOException e) { 85 | throw new JedisConnectionException(e); 86 | } 87 | return null; 88 | } 89 | 90 | private static byte[] processStatusCodeReply(final RedisInputStream is) { 91 | return SafeEncoder.encode(is.readLine()); 92 | } 93 | 94 | private static byte[] processBulkReply(final RedisInputStream is) { 95 | int len = Integer.parseInt(is.readLine()); 96 | if (len == -1) { 97 | return null; 98 | } 99 | byte[] read = new byte[len]; 100 | int offset = 0; 101 | try { 102 | while (offset < len) { 103 | offset += is.read(read, offset, (len - offset)); 104 | } 105 | // read 2 more bytes for the command delimiter 106 | is.readByte(); 107 | is.readByte(); 108 | } catch (IOException e) { 109 | throw new JedisConnectionException(e); 110 | } 111 | 112 | return read; 113 | } 114 | 115 | private static Long processInteger(final RedisInputStream is) { 116 | String num = is.readLine(); 117 | return Long.valueOf(num); 118 | } 119 | 120 | private static List processMultiBulkReply(final RedisInputStream is) { 121 | int num = Integer.parseInt(is.readLine()); 122 | if (num == -1) { 123 | return null; 124 | } 125 | List ret = new ArrayList(num); 126 | for (int i = 0; i < num; i++) { 127 | try { 128 | ret.add(process(is)); 129 | } catch (JedisDataException e) { 130 | ret.add(e); 131 | } 132 | } 133 | return ret; 134 | } 135 | 136 | public static Object read(final RedisInputStream is) { 137 | return process(is); 138 | } 139 | 140 | public static final byte[] toByteArray(final boolean value) { 141 | return toByteArray(value ? 1 : 0); 142 | } 143 | 144 | public static final byte[] toByteArray(final int value) { 145 | return SafeEncoder.encode(String.valueOf(value)); 146 | } 147 | 148 | public static final byte[] toByteArray(final long value) { 149 | return SafeEncoder.encode(String.valueOf(value)); 150 | } 151 | 152 | public static final byte[] toByteArray(final double value) { 153 | return SafeEncoder.encode(String.valueOf(value)); 154 | } 155 | 156 | public static enum Command { 157 | 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; 158 | 159 | public final byte[] raw; 160 | 161 | Command() { 162 | raw = SafeEncoder.encode(this.name()); 163 | } 164 | } 165 | 166 | public static enum Keyword { 167 | 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; 168 | public final byte[] raw; 169 | 170 | Keyword() { 171 | raw = SafeEncoder.encode(this.name().toLowerCase()); 172 | } 173 | } 174 | } 175 | -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/RedisPipeline.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.util.List; 4 | import java.util.Map; 5 | import java.util.Set; 6 | 7 | /** 8 | * @author guy 9 | */ 10 | public interface RedisPipeline { 11 | Response append(String key, String value); 12 | 13 | Response> blpop(String arg); 14 | 15 | Response> brpop(String arg); 16 | 17 | Response decr(String key); 18 | 19 | Response decrBy(String key, long integer); 20 | 21 | Response del(String key); 22 | 23 | Response echo(String string); 24 | 25 | Response exists(String key); 26 | 27 | Response expire(String key, int seconds); 28 | 29 | Response expireAt(String key, long unixTime); 30 | 31 | Response get(String key); 32 | 33 | Response getbit(String key, long offset); 34 | 35 | 36 | 37 | Response getrange(String key, long startOffset, 38 | long endOffset); 39 | 40 | Response getSet(String key, String value); 41 | 42 | Response hdel(String key, String field); 43 | 44 | Response hexists(String key, String field); 45 | 46 | Response hget(String key, String field); 47 | 48 | Response> hgetAll(String key); 49 | 50 | Response hincrBy(String key, String field, long value); 51 | 52 | Response> hkeys(String key); 53 | 54 | Response hlen(String key); 55 | 56 | Response> hmget(String key, String... fields); 57 | 58 | Response hmset(String key, Map hash); 59 | 60 | Response hset(String key, String field, String value); 61 | 62 | Response hsetnx(String key, String field, String value); 63 | 64 | Response> hvals(String key); 65 | 66 | Response incr(String key); 67 | 68 | Response incrBy(String key, long integer); 69 | 70 | Response lindex(String key, int index); 71 | 72 | Response linsert(String key, BinaryClient.LIST_POSITION where, 73 | String pivot, String value); 74 | 75 | Response llen(String key); 76 | 77 | Response lpop(String key); 78 | 79 | Response lpush(String key, String... string); 80 | 81 | Response lpushx(String key, String... string); 82 | 83 | Response> lrange(String key, long start, long end); 84 | 85 | Response lrem(String key, long count, String value); 86 | 87 | Response lset(String key, long index, String value); 88 | 89 | Response ltrim(String key, long start, long end); 90 | 91 | Response move(String key, int dbIndex); 92 | 93 | Response persist(String key); 94 | 95 | Response rpop(String key); 96 | 97 | Response rpush(String key, String... string); 98 | 99 | Response rpushx(String key, String... string); 100 | 101 | Response sadd(String key, String... member); 102 | 103 | Response scard(String key); 104 | 105 | Response sismember(String key, String member); 106 | 107 | Response set(String key, String value); 108 | 109 | Response setbit(String key, long offset, boolean value); 110 | 111 | Response setex(String key, int seconds, String value); 112 | 113 | Response setnx(String key, String value); 114 | 115 | Response setrange(String key, long offset, String value); 116 | 117 | Response> smembers(String key); 118 | 119 | Response> sort(String key); 120 | 121 | Response> sort(String key, 122 | SortingParams sortingParameters); 123 | 124 | Response spop(String key); 125 | 126 | Response srandmember(String key); 127 | 128 | Response srem(String key, String member); 129 | 130 | Response strlen(String key); 131 | 132 | Response substr(String key, int start, int end); 133 | 134 | Response ttl(String key); 135 | 136 | Response type(String key); 137 | 138 | Response zadd(String key, double score, String member); 139 | 140 | Response zcard(String key); 141 | 142 | Response zcount(String key, double min, double max); 143 | 144 | Response zincrby(String key, double score, String member); 145 | 146 | Response> zrange(String key, int start, int end); 147 | 148 | Response> zrangeByScore(String key, double min, 149 | double max); 150 | 151 | Response> zrangeByScore(String key, String min, 152 | String max); 153 | 154 | Response> zrangeByScore(String key, double min, 155 | double max, int offset, int count); 156 | 157 | Response> zrangeByScoreWithScores(String key, double min, 158 | double max); 159 | 160 | Response> zrangeByScoreWithScores(String key, double min, 161 | double max, int offset, int count); 162 | 163 | Response> zrevrangeByScore(String key, double max, 164 | double min); 165 | 166 | Response> zrevrangeByScore(String key, String max, 167 | String min); 168 | 169 | Response> zrevrangeByScore(String key, double max, 170 | double min, int offset, int count); 171 | 172 | Response> zrevrangeByScoreWithScores(String key, 173 | double max, double min); 174 | 175 | Response> zrevrangeByScoreWithScores(String key, 176 | double max, double min, int offset, int count); 177 | 178 | Response> zrangeWithScores(String key, int start, int end); 179 | 180 | Response zrank(String key, String member); 181 | 182 | Response zrem(String key, String member); 183 | 184 | Response zremrangeByRank(String key, int start, int end); 185 | 186 | Response zremrangeByScore(String key, double start, double end); 187 | 188 | Response> zrevrange(String key, int start, int end); 189 | 190 | Response> zrevrangeWithScores(String key, int start, 191 | int end); 192 | 193 | Response zrevrank(String key, String member); 194 | 195 | Response zscore(String key, String member); 196 | 197 | Response bitcount(String key); 198 | 199 | Response bitcount(String key, long start, long end); 200 | } 201 | -------------------------------------------------------------------------------- /src/test/java/redis/clients/jedis/tests/commands/BinaryValuesCommandsTest.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis.tests.commands; 2 | 3 | import java.util.ArrayList; 4 | import java.util.Arrays; 5 | import java.util.List; 6 | 7 | import org.junit.Before; 8 | import org.junit.Test; 9 | 10 | import redis.clients.jedis.Protocol.Keyword; 11 | import redis.clients.jedis.exceptions.JedisDataException; 12 | 13 | public class BinaryValuesCommandsTest extends JedisCommandTestBase { 14 | byte[] bfoo = { 0x01, 0x02, 0x03, 0x04 }; 15 | byte[] bbar = { 0x05, 0x06, 0x07, 0x08 }; 16 | byte[] binaryValue; 17 | 18 | @Before 19 | public void startUp() { 20 | StringBuilder sb = new StringBuilder(); 21 | 22 | for (int n = 0; n < 1000; n++) { 23 | sb.append("A"); 24 | } 25 | 26 | binaryValue = sb.toString().getBytes(); 27 | } 28 | 29 | @Test 30 | public void setAndGet() { 31 | String status = jedis.set(bfoo, binaryValue); 32 | assertTrue(Keyword.OK.name().equalsIgnoreCase(status)); 33 | 34 | byte[] value = jedis.get(bfoo); 35 | assertTrue(Arrays.equals(binaryValue, value)); 36 | 37 | assertNull(jedis.get(bbar)); 38 | } 39 | 40 | @Test 41 | public void getSet() { 42 | byte[] value = jedis.getSet(bfoo, binaryValue); 43 | assertNull(value); 44 | value = jedis.get(bfoo); 45 | assertTrue(Arrays.equals(binaryValue, value)); 46 | } 47 | 48 | @Test 49 | public void mget() { 50 | List values = jedis.mget(bfoo, bbar); 51 | List expected = new ArrayList(); 52 | expected.add(null); 53 | expected.add(null); 54 | 55 | assertEquals(expected, values); 56 | 57 | jedis.set(bfoo, binaryValue); 58 | 59 | expected = new ArrayList(); 60 | expected.add(binaryValue); 61 | expected.add(null); 62 | values = jedis.mget(bfoo, bbar); 63 | 64 | assertEquals(expected, values); 65 | 66 | jedis.set(bbar, bfoo); 67 | 68 | expected = new ArrayList(); 69 | expected.add(binaryValue); 70 | expected.add(bfoo); 71 | values = jedis.mget(bfoo, bbar); 72 | 73 | assertEquals(expected, values); 74 | } 75 | 76 | @Test 77 | public void setnx() { 78 | long status = jedis.setnx(bfoo, binaryValue); 79 | assertEquals(1, status); 80 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 81 | 82 | status = jedis.setnx(bfoo, bbar); 83 | assertEquals(0, status); 84 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 85 | } 86 | 87 | @Test 88 | public void setex() { 89 | String status = jedis.setex(bfoo, 20, binaryValue); 90 | assertEquals(Keyword.OK.name(), status); 91 | long ttl = jedis.ttl(bfoo); 92 | assertTrue(ttl > 0 && ttl <= 20); 93 | } 94 | 95 | @Test 96 | public void mset() { 97 | String status = jedis.mset(bfoo, binaryValue, bbar, bfoo); 98 | assertEquals(Keyword.OK.name(), status); 99 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 100 | assertTrue(Arrays.equals(bfoo, jedis.get(bbar))); 101 | } 102 | 103 | @Test 104 | public void msetnx() { 105 | long status = jedis.msetnx(bfoo, binaryValue, bbar, bfoo); 106 | assertEquals(1, status); 107 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 108 | assertTrue(Arrays.equals(bfoo, jedis.get(bbar))); 109 | 110 | status = jedis.msetnx(bfoo, bbar, "bar2".getBytes(), "foo2".getBytes()); 111 | assertEquals(0, status); 112 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 113 | assertTrue(Arrays.equals(bfoo, jedis.get(bbar))); 114 | } 115 | 116 | @Test(expected = JedisDataException.class) 117 | public void incrWrongValue() { 118 | jedis.set(bfoo, binaryValue); 119 | jedis.incr(bfoo); 120 | } 121 | 122 | @Test 123 | public void incr() { 124 | long value = jedis.incr(bfoo); 125 | assertEquals(1, value); 126 | value = jedis.incr(bfoo); 127 | assertEquals(2, value); 128 | } 129 | 130 | @Test(expected = JedisDataException.class) 131 | public void incrByWrongValue() { 132 | jedis.set(bfoo, binaryValue); 133 | jedis.incrBy(bfoo, 2); 134 | } 135 | 136 | @Test 137 | public void incrBy() { 138 | long value = jedis.incrBy(bfoo, 2); 139 | assertEquals(2, value); 140 | value = jedis.incrBy(bfoo, 2); 141 | assertEquals(4, value); 142 | } 143 | 144 | @Test(expected = JedisDataException.class) 145 | public void decrWrongValue() { 146 | jedis.set(bfoo, binaryValue); 147 | jedis.decr(bfoo); 148 | } 149 | 150 | @Test 151 | public void decr() { 152 | long value = jedis.decr(bfoo); 153 | assertEquals(-1, value); 154 | value = jedis.decr(bfoo); 155 | assertEquals(-2, value); 156 | } 157 | 158 | @Test(expected = JedisDataException.class) 159 | public void decrByWrongValue() { 160 | jedis.set(bfoo, binaryValue); 161 | jedis.decrBy(bfoo, 2); 162 | } 163 | 164 | @Test 165 | public void decrBy() { 166 | long value = jedis.decrBy(bfoo, 2); 167 | assertEquals(-2, value); 168 | value = jedis.decrBy(bfoo, 2); 169 | assertEquals(-4, value); 170 | } 171 | 172 | @Test 173 | public void append() { 174 | byte[] first512 = new byte[512]; 175 | System.arraycopy(binaryValue, 0, first512, 0, 512); 176 | long value = jedis.append(bfoo, first512); 177 | assertEquals(512, value); 178 | assertTrue(Arrays.equals(first512, jedis.get(bfoo))); 179 | 180 | byte[] rest = new byte[binaryValue.length - 512]; 181 | System.arraycopy(binaryValue, 512, rest, 0, binaryValue.length - 512); 182 | value = jedis.append(bfoo, rest); 183 | assertEquals(binaryValue.length, value); 184 | 185 | assertTrue(Arrays.equals(binaryValue, jedis.get(bfoo))); 186 | } 187 | 188 | @Test 189 | public void substr() { 190 | jedis.set(bfoo, binaryValue); 191 | 192 | byte[] first512 = new byte[512]; 193 | System.arraycopy(binaryValue, 0, first512, 0, 512); 194 | byte[] rfirst512 = jedis.substr(bfoo, 0, 511); 195 | assertTrue(Arrays.equals(first512, rfirst512)); 196 | 197 | byte[] last512 = new byte[512]; 198 | System 199 | .arraycopy(binaryValue, binaryValue.length - 512, last512, 0, 200 | 512); 201 | assertTrue(Arrays.equals(last512, jedis.substr(bfoo, -512, -1))); 202 | 203 | assertTrue(Arrays.equals(binaryValue, jedis.substr(bfoo, 0, -1))); 204 | 205 | assertTrue(Arrays.equals(last512, jedis.substr(bfoo, 206 | binaryValue.length - 512, 100000))); 207 | } 208 | 209 | @Test 210 | public void strlen() { 211 | jedis.set(bfoo, binaryValue); 212 | assertEquals(binaryValue.length, jedis.strlen(bfoo).intValue()); 213 | } 214 | } -------------------------------------------------------------------------------- /src/main/java/redis/clients/jedis/Connection.java: -------------------------------------------------------------------------------- 1 | package redis.clients.jedis; 2 | 3 | import java.io.IOException; 4 | import java.net.InetSocketAddress; 5 | import java.net.Socket; 6 | import java.net.SocketException; 7 | import java.util.ArrayList; 8 | import java.util.List; 9 | 10 | import redis.clients.jedis.Protocol.Command; 11 | import redis.clients.jedis.exceptions.JedisConnectionException; 12 | import redis.clients.jedis.exceptions.JedisDataException; 13 | import redis.clients.jedis.exceptions.JedisException; 14 | import redis.clients.util.RedisInputStream; 15 | import redis.clients.util.RedisOutputStream; 16 | import redis.clients.util.SafeEncoder; 17 | 18 | public class Connection { 19 | private String host; 20 | private int port = Protocol.DEFAULT_PORT; 21 | private Socket socket; 22 | private RedisOutputStream outputStream; 23 | private RedisInputStream inputStream; 24 | private int pipelinedCommands = 0; 25 | private int timeout = Protocol.DEFAULT_TIMEOUT; 26 | 27 | public Socket getSocket() { 28 | return socket; 29 | } 30 | 31 | public int getTimeout() { 32 | return timeout; 33 | } 34 | 35 | public void setTimeout(final int timeout) { 36 | this.timeout = timeout; 37 | } 38 | 39 | public void setTimeoutInfinite() { 40 | try { 41 | if(!isConnected()) { 42 | connect(); 43 | } 44 | socket.setKeepAlive(true); 45 | socket.setSoTimeout(0); 46 | } catch (SocketException ex) { 47 | throw new JedisException(ex); 48 | } 49 | } 50 | 51 | public void rollbackTimeout() { 52 | try { 53 | socket.setSoTimeout(timeout); 54 | socket.setKeepAlive(false); 55 | } catch (SocketException ex) { 56 | throw new JedisException(ex); 57 | } 58 | } 59 | 60 | public Connection(final String host) { 61 | super(); 62 | this.host = host; 63 | } 64 | 65 | protected void flush() { 66 | try { 67 | outputStream.flush(); 68 | } catch (IOException e) { 69 | throw new JedisConnectionException(e); 70 | } 71 | } 72 | 73 | protected Connection sendCommand(final Command cmd, final String... args) { 74 | final byte[][] bargs = new byte[args.length][]; 75 | for (int i = 0; i < args.length; i++) { 76 | bargs[i] = SafeEncoder.encode(args[i]); 77 | } 78 | return sendCommand(cmd, bargs); 79 | } 80 | 81 | protected Connection sendCommand(final Command cmd, final byte[]... args) { 82 | connect(); 83 | Protocol.sendCommand(outputStream, cmd, args); 84 | pipelinedCommands++; 85 | return this; 86 | } 87 | 88 | protected Connection sendCommand(final Command cmd) { 89 | connect(); 90 | Protocol.sendCommand(outputStream, cmd, new byte[0][]); 91 | pipelinedCommands++; 92 | return this; 93 | } 94 | 95 | public Connection(final String host, final int port) { 96 | super(); 97 | this.host = host; 98 | this.port = port; 99 | } 100 | 101 | public String getHost() { 102 | return host; 103 | } 104 | 105 | public void setHost(final String host) { 106 | this.host = host; 107 | } 108 | 109 | public int getPort() { 110 | return port; 111 | } 112 | 113 | public void setPort(final int port) { 114 | this.port = port; 115 | } 116 | 117 | public Connection() { 118 | 119 | } 120 | 121 | public void connect() { 122 | if (!isConnected()) { 123 | try { 124 | socket = new Socket(); 125 | //->@wjw_add 126 | socket.setReuseAddress(true); 127 | socket.setKeepAlive(true); //Will monitor the TCP connection is valid 128 | socket.setTcpNoDelay(true); //Socket buffer Whetherclosed, to ensure timely delivery of data 129 | socket.setSoLinger(true,0); //Control calls close () method, the underlying socket is closed immediately 130 | //<-@wjw_add 131 | 132 | socket.connect(new InetSocketAddress(host, port), timeout); 133 | socket.setSoTimeout(timeout); 134 | outputStream = new RedisOutputStream(socket.getOutputStream()); 135 | inputStream = new RedisInputStream(socket.getInputStream()); 136 | } catch (IOException ex) { 137 | throw new JedisConnectionException(ex); 138 | } 139 | } 140 | } 141 | 142 | public void disconnect() { 143 | if (isConnected()) { 144 | try { 145 | inputStream.close(); 146 | outputStream.close(); 147 | if (!socket.isClosed()) { 148 | socket.close(); 149 | } 150 | } catch (IOException ex) { 151 | throw new JedisConnectionException(ex); 152 | } 153 | } 154 | } 155 | 156 | public boolean isConnected() { 157 | return socket != null && socket.isBound() && !socket.isClosed() 158 | && socket.isConnected() && !socket.isInputShutdown() 159 | && !socket.isOutputShutdown(); 160 | } 161 | 162 | protected String getStatusCodeReply() { 163 | flush(); 164 | pipelinedCommands--; 165 | final byte[] resp = (byte[]) Protocol.read(inputStream); 166 | if (null == resp) { 167 | return null; 168 | } else { 169 | return SafeEncoder.encode(resp); 170 | } 171 | } 172 | 173 | public String getBulkReply() { 174 | final byte[] result = getBinaryBulkReply(); 175 | if (null != result) { 176 | return SafeEncoder.encode(result); 177 | } else { 178 | return null; 179 | } 180 | } 181 | 182 | public byte[] getBinaryBulkReply() { 183 | flush(); 184 | pipelinedCommands--; 185 | return (byte[]) Protocol.read(inputStream); 186 | } 187 | 188 | public Long getIntegerReply() { 189 | flush(); 190 | pipelinedCommands--; 191 | return (Long) Protocol.read(inputStream); 192 | } 193 | 194 | public List getMultiBulkReply() { 195 | return BuilderFactory.STRING_LIST.build(getBinaryMultiBulkReply()); 196 | } 197 | 198 | @SuppressWarnings("unchecked") 199 | public List getBinaryMultiBulkReply() { 200 | flush(); 201 | pipelinedCommands--; 202 | return (List) Protocol.read(inputStream); 203 | } 204 | 205 | @SuppressWarnings("unchecked") 206 | public List getObjectMultiBulkReply() { 207 | flush(); 208 | pipelinedCommands--; 209 | return (List) Protocol.read(inputStream); 210 | } 211 | 212 | @SuppressWarnings("unchecked") 213 | public List getIntegerMultiBulkReply() { 214 | flush(); 215 | pipelinedCommands--; 216 | return (List) Protocol.read(inputStream); 217 | } 218 | 219 | public List getAll() { 220 | return getAll(0); 221 | } 222 | 223 | public List getAll(int except) { 224 | List all = new ArrayList(); 225 | flush(); 226 | while (pipelinedCommands > except) { 227 | try{ 228 | all.add(Protocol.read(inputStream)); 229 | }catch(JedisDataException e){ 230 | all.add(e); 231 | } 232 | pipelinedCommands--; 233 | } 234 | return all; 235 | } 236 | 237 | public Object getOne() { 238 | flush(); 239 | pipelinedCommands--; 240 | return Protocol.read(inputStream); 241 | } 242 | } 243 | --------------------------------------------------------------------------------