From 4bf438f563fe2d745c4b5cbb260113a68260abcd Mon Sep 17 00:00:00 2001 From: Christoph Strobl Date: Mon, 17 Mar 2014 13:48:33 +0100 Subject: [PATCH] DATAREDIS-270 - Add support for 'CLIENT GETNAME'. Support for getting client connection name has been added for 'jedis', 'jredis' and 'srp' drivers. Using 'jredis' will throw 'UnsupportedOperationException'. Original Pull Request: #51 --- .../appendix/appendix-command-reference.xml | 4 +-- .../DefaultStringRedisConnection.java | 25 ++++++++++++------- .../redis/connection/RedisServerCommands.java | 9 +++++++ .../connection/jedis/JedisConnection.java | 13 ++++++++++ .../connection/jredis/JredisConnection.java | 9 +++++++ .../connection/lettuce/LettuceConnection.java | 24 ++++++++++++++++++ .../connection/lettuce/LettuceConverters.java | 21 ++++++++++++++++ .../redis/connection/srp/SrpConnection.java | 20 +++++++++++++++ .../redis/connection/srp/SrpConverters.java | 21 +++++++++++++++- .../DefaultStringRedisConnectionTests.java | 10 ++++++++ .../jedis/JedisConnectionUnitTestSuite.java | 24 ++++++++++++++++++ .../jredis/JRedisConnectionUnitTests.java | 9 +++++++ .../LettuceConnectionUnitTestSuite.java | 10 ++++++++ .../srp/SrpConnectionUnitTestSuite.java | 20 +++++++++++++++ 14 files changed, 207 insertions(+), 12 deletions(-) diff --git a/docs/src/reference/docbook/appendix/appendix-command-reference.xml b/docs/src/reference/docbook/appendix/appendix-command-reference.xml index 224230164..4a1d46111 100644 --- a/docs/src/reference/docbook/appendix/appendix-command-reference.xml +++ b/docs/src/reference/docbook/appendix/appendix-command-reference.xml @@ -1,4 +1,4 @@ - +# Spring Data Redis Supported Commands @@ -23,8 +23,8 @@ BLPOPX BRPOPX BRPOPLPUSHX - CLIENT GETNAME- CLIENT KILLX + CLIENT GETNAMEX CLIENT LIST- CLIENT SETNAMEX CONFIG GETX diff --git a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java index beeac1aa9..e8ac41eed 100644 --- a/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/DefaultStringRedisConnection.java @@ -2191,15 +2191,6 @@ public class DefaultStringRedisConnection implements StringRedisConnection { return this.delegate.time(); } - /* - * (non-Javadoc) - * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(byte[]) - */ - @Override - public void killClient(String host, int port) { - this.delegate.killClient(host, port); - } - /** * Specifies if pipelined and tx results should be deserialized to Strings. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the underlying connection @@ -2257,4 +2248,20 @@ public class DefaultStringRedisConnection implements StringRedisConnection { setClientName(this.serializer.serialize(name)); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#killClient(byte[]) + */ + @Override + public void killClient(String host, int port) { + this.delegate.killClient(host, port); + } + + /* + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + return this.delegate.getClientName(); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java index 3219df9f4..1268d8375 100644 --- a/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java +++ b/src/main/java/org/springframework/data/redis/connection/RedisServerCommands.java @@ -177,4 +177,13 @@ public interface RedisServerCommands { * @since 1.3 */ void setClientName(byte[] name); + + /** + * Returns the name of the current connection. + * + * @see http://redis.io/commands/client-getname + * @return + * @since 1.3 + */ + String getClientName(); } diff --git a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java index 56a4df482..406142381 100644 --- a/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jedis/JedisConnection.java @@ -2841,6 +2841,19 @@ public class JedisConnection implements RedisConnection { jedis.clientSetname(name); } + /* + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + + if (isPipelined() || isQueueing()) { + throw new UnsupportedOperationException(); + } + + return jedis.clientGetname(); + } + /** * Specifies if pipelined results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Jedis driver diff --git a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java index 2e4656c33..24613a97f 100644 --- a/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/jredis/JredisConnection.java @@ -1195,4 +1195,13 @@ public class JredisConnection implements RedisConnection { public void setClientName(byte[] name) { throw new UnsupportedOperationException("'CLIENT SETNAME' is not supported by the JRedis driver."); } + + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + throw new UnsupportedOperationException("The 'CLIENT GETNAME' command is not supported by the JRedis driver."); + } } diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java index 96836323d..aa1750e25 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConnection.java @@ -2935,6 +2935,30 @@ public class LettuceConnection implements RedisConnection { getAsyncConnection().clientSetname(name); } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + + try { + + if (isPipelined()) { + pipeline(new LettuceResult(getAsyncConnection().clientGetname(), LettuceConverters.bytesToString())); + return null; + } + if (isQueueing()) { + transaction(new LettuceTxResult(getConnection().clientGetname(), LettuceConverters.bytesToString())); + return null; + } + + return LettuceConverters.toString(getConnection().clientGetname()); + } catch (Exception ex) { + throw convertLettuceAccessException(ex); + } + } + /** * Specifies if pipelined and transaction results should be converted to the expected data type. If false, results of * {@link #closePipeline()} and {@link #exec()} will be of the type returned by the Lettuce driver diff --git a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java index 46d01c1ab..11cac3959 100644 --- a/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/lettuce/LettuceConverters.java @@ -16,6 +16,7 @@ package org.springframework.data.redis.connection.lettuce; import java.util.ArrayList; +import java.util.Arrays; import java.util.Date; import java.util.LinkedHashSet; import java.util.List; @@ -47,6 +48,7 @@ abstract public class LettuceConverters extends Converters { private static final Converter DATE_TO_LONG; private static final Converter, Set> BYTES_LIST_TO_BYTES_SET; + private static final Converter BYTES_TO_STRING; private static final Converter, List> BYTES_SET_TO_BYTES_LIST; private static final Converter, List> KEY_VALUE_TO_BYTES_LIST; private static final Converter>, Set> SCORED_VALUES_TO_TUPLE_SET; @@ -65,6 +67,17 @@ abstract public class LettuceConverters extends Converters { return results != null ? new LinkedHashSet(results) : null; } + }; + BYTES_TO_STRING = new Converter() { + + @Override + public String convert(byte[] source) { + if (source == null || Arrays.equals(source, new byte[0])) { + return null; + } + return new String(source); + } + }; BYTES_SET_TO_BYTES_LIST = new Converter, List>() { public List convert(Set results) { @@ -110,6 +123,10 @@ abstract public class LettuceConverters extends Converters { return BYTES_LIST_TO_BYTES_SET; } + public static Converter bytesToString() { + return BYTES_TO_STRING; + } + public static Converter, List> keyValueToBytesList() { return KEY_VALUE_TO_BYTES_LIST; } @@ -158,6 +175,10 @@ abstract public class LettuceConverters extends Converters { return EXCEPTION_CONVERTER.convert(ex); } + public static String toString(byte[] source) { + return BYTES_TO_STRING.convert(source); + } + public static ScriptOutputType toScriptOutputType(ReturnType returnType) { switch (returnType) { case BOOLEAN: diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java index bda3701ee..7ebb9a5c4 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConnection.java @@ -2260,6 +2260,26 @@ public class SrpConnection implements RedisConnection { } } + /* + * (non-Javadoc) + * @see org.springframework.data.redis.connection.RedisServerCommands#getClientName() + */ + @Override + public String getClientName() { + + try { + + if (isPipelined()) { + pipeline(new SrpGenericResult(pipeline.client_getname(), SrpConverters.replyToString())); + return null; + } + + return SrpConverters.toString(client.client_getname()); + } catch (Exception ex) { + throw convertSrpAccessException(ex); + } + } + private List closeTransaction() { List results = Collections.emptyList(); if (txTracker != null) { diff --git a/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java b/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java index ee6b03217..612839335 100644 --- a/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java +++ b/src/main/java/org/springframework/data/redis/connection/srp/SrpConverters.java @@ -35,7 +35,6 @@ import org.springframework.data.redis.connection.RedisStringCommands.BitOperatio import org.springframework.data.redis.connection.RedisZSetCommands.Tuple; import org.springframework.data.redis.connection.convert.Converters; import org.springframework.util.Assert; -import org.springframework.util.NumberUtils; import redis.client.RedisException; import redis.reply.IntegerReply; @@ -61,6 +60,7 @@ abstract public class SrpConverters extends Converters { private static final Converter> REPLIES_TO_BYTES_MAP; private static final Converter> REPLIES_TO_BOOLEAN_LIST; private static final Converter> REPLIES_TO_STRING_LIST; + private static final Converter REPLY_TO_STRING; private static final Converter BYTES_TO_PROPERTIES; private static final Converter BYTES_TO_STRING; private static final Converter BYTES_TO_DOUBLE; @@ -171,6 +171,16 @@ abstract public class SrpConverters extends Converters { return results; } }; + REPLY_TO_STRING = new Converter() { + + @Override + public String convert(Reply source) { + if (source == null) { + return null; + } + return SrpConverters.toString((byte[]) source.data()); + } + }; } public static Converter> repliesToBytesList() { @@ -201,6 +211,10 @@ abstract public class SrpConverters extends Converters { return BYTES_TO_STRING; } + public static Converter replyToString() { + return REPLY_TO_STRING; + } + public static Converter> repliesToBooleanList() { return REPLIES_TO_BOOLEAN_LIST; } @@ -237,6 +251,10 @@ abstract public class SrpConverters extends Converters { return REPLIES_TO_BYTES_MAP.convert(source); } + public static String toString(Reply source) { + return REPLY_TO_STRING.convert(source); + } + public static String toString(byte[] source) { return BYTES_TO_STRING.convert(source); } @@ -293,4 +311,5 @@ abstract public class SrpConverters extends Converters { public static List toStringList(String source) { return Collections.singletonList(source); } + } diff --git a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java index 474de96ee..162b5f79a 100644 --- a/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java +++ b/src/test/java/org/springframework/data/redis/connection/DefaultStringRedisConnectionTests.java @@ -1720,6 +1720,16 @@ public class DefaultStringRedisConnectionTests { verify(nativeConnection, times(1)).setClientName(eq("foo".getBytes())); } + /** + * @see DATAREDIS-270 + */ + @Test + public void testGetClientNameIsDelegatedCorrectlyToNativeConnection() { + + actual.add(connection.getClientName()); + verify(nativeConnection, times(1)).getClientName(); + } + protected List getResults() { return actual; } diff --git a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionUnitTestSuite.java b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionUnitTestSuite.java index 6cca22922..1effabe57 100644 --- a/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionUnitTestSuite.java +++ b/src/test/java/org/springframework/data/redis/connection/jedis/JedisConnectionUnitTestSuite.java @@ -123,6 +123,17 @@ public class JedisConnectionUnitTestSuite { connection.killClient("127.0.0.1", 1001); verifyNativeConnectionInvocation().clientKill(eq("127.0.0.1:1001")); } + + /** + * @see DATAREDIS-270 + */ + @Test + public void getClientNameShouldSendRequestCorrectly() { + + connection.getClientName(); + verifyNativeConnectionInvocation().clientGetname(); + } + } public static class JedisConnectionPipelineUnitTests extends JedisConnectionUnitTests { @@ -151,10 +162,23 @@ public class JedisConnectionUnitTestSuite { super.shutdownSaveShouldBeSentCorrectlyUsingLuaScript(); } + /** + * @see DATAREDIS-267 + */ @Test(expected = UnsupportedOperationException.class) public void killClientShouldDelegateCallCorrectly() { super.killClientShouldDelegateCallCorrectly(); } + + /** + * @see DATAREDIS-270 + */ + @Override + @Test(expected = UnsupportedOperationException.class) + public void getClientNameShouldSendRequestCorrectly() { + super.getClientNameShouldSendRequestCorrectly(); + } + } /** diff --git a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionUnitTests.java b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionUnitTests.java index 14b60f0de..1172c080c 100644 --- a/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionUnitTests.java +++ b/src/test/java/org/springframework/data/redis/connection/jredis/JRedisConnectionUnitTests.java @@ -56,4 +56,13 @@ public class JRedisConnectionUnitTests extends AbstractConnectionUnitTestBase { @@ -135,6 +145,16 @@ public class SrpConnectionUnitTestSuite { verifyNativeConnectionInvocation().shutdown("NOSAVE".getBytes(Charsets.UTF_8), null); } + /** + * @see DATAREDIS-270 + */ + @Test + public void getClientNameShouldSendRequestCorrectly() { + + connection.getClientName(); + verifyNativeConnectionInvocation().client_getname(); + } + } }