DATAREDIS-268 - Add support for 'CLIENT LIST'.

'RedisConnection' and 'RedisTemplate' have been extended by 'getClientList' retrieving client informations from redis. 'RedisClientInfo' provides access via specified getters as well as an more general approach directly using the keys (like 'qubuf').

The operation is available for 'jedis', 'lettuce' and 'srp'.

Original Pull Request: #53
This commit is contained in:
Christoph Strobl
2014-03-24 09:05:33 +01:00
committed by Thomas Darimont
parent 4bf438f563
commit 2679405e96
28 changed files with 937 additions and 17 deletions

View File

@@ -32,6 +32,7 @@ import org.springframework.data.redis.RedisSystemException;
import org.springframework.data.redis.connection.convert.ListConverter;
import org.springframework.data.redis.connection.convert.MapConverter;
import org.springframework.data.redis.connection.convert.SetConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.StringRedisSerializer;
import org.springframework.util.Assert;
@@ -2191,6 +2192,11 @@ public class DefaultStringRedisConnection implements StringRedisConnection {
return this.delegate.time();
}
@Override
public List<RedisClientInfo> getClientList() {
return this.delegate.getClientList();
}
/**
* 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

View File

@@ -18,6 +18,8 @@ package org.springframework.data.redis.connection;
import java.util.List;
import java.util.Properties;
import org.springframework.data.redis.core.types.RedisClientInfo;
/**
* Server-specific commands supported by Redis.
*
@@ -186,4 +188,13 @@ public interface RedisServerCommands {
* @since 1.3
*/
String getClientName();
/**
* Request information and statistics about connected clients.
*
* @return {@link List} of {@link RedisClientInfo} objects.
* @since 1.3
* @see http://redis.io/commands/client-list
*/
List<RedisClientInfo> getClientList();
}

View File

@@ -22,6 +22,7 @@ import java.util.Set;
import org.springframework.data.redis.core.RedisCallback;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
@@ -301,4 +302,10 @@ public interface StringRedisConnection extends RedisConnection {
* @sice 1.3
*/
void setClientName(String name);
/**
* @see RedisConnection#getClientList()
* @since 1.3
*/
List<RedisClientInfo> getClientList();
}

View File

@@ -0,0 +1,52 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.connection.convert;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import org.springframework.core.convert.converter.Converter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.core.types.RedisClientInfo.RedisClientInfoBuilder;
/**
* {@link Converter} implementation to create one {@link RedisClientInfo} per line entry in given {@link String} array.
*
* <pre>
* ## sample of single line
* addr=127.0.0.1:60311 fd=6 name= age=4059 idle=0 flags=N db=0 sub=0 psub=0 multi=-1 qbuf=0 qbuf-free=32768 obl=0 oll=0 omem=0 events=r cmd=client
* </pre>
*
* @author Christoph Strobl
* @since 1.3
*/
public class StringToRedisClientInfoConverter implements Converter<String[], List<RedisClientInfo>> {
@Override
public List<RedisClientInfo> convert(String[] lines) {
if (lines == null) {
return Collections.emptyList();
}
List<RedisClientInfo> infos = new ArrayList<RedisClientInfo>(lines.length);
for (String line : lines) {
infos.add(RedisClientInfoBuilder.fromString(line));
}
return infos;
}
}

View File

@@ -42,6 +42,7 @@ import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.connection.Subscription;
import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.TransactionResultConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -2854,6 +2855,18 @@ public class JedisConnection implements RedisConnection {
return jedis.clientGetname();
}
/*
* @see org.springframework.data.redis.connection.RedisServerCommands#getClientName()
*/
@Override
public List<RedisClientInfo> getClientList() {
if (isQueueing() || isPipelined()) {
throw new UnsupportedOperationException("'CLIENT LIST' is not supported in in pipeline / multi mode.");
}
return JedisConverters.toListOfRedisClientInformation(this.jedis.clientList());
}
/**
* 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

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2013 the original author or authors.
* Copyright 2013-2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -15,6 +15,8 @@
*/
package org.springframework.data.redis.connection.jedis;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Set;
@@ -31,7 +33,10 @@ import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.ListConverter;
import org.springframework.data.redis.connection.convert.MapConverter;
import org.springframework.data.redis.connection.convert.SetConverter;
import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import redis.clients.jedis.BinaryClient.LIST_POSITION;
import redis.clients.jedis.BitOP;
@@ -42,6 +47,7 @@ import redis.clients.util.SafeEncoder;
* Jedis type converters
*
* @author Jennifer Hickey
* @author Christoph Strobl
*/
abstract public class JedisConverters extends Converters {
@@ -51,6 +57,7 @@ abstract public class JedisConverters extends Converters {
private static final MapConverter<String, byte[]> STRING_MAP_TO_BYTE_MAP;
private static final SetConverter<redis.clients.jedis.Tuple, Tuple> TUPLE_SET_TO_TUPLE_SET;
private static final Converter<Exception, DataAccessException> EXCEPTION_CONVERTER = new JedisExceptionConverter();
private static final Converter<String[], List<RedisClientInfo>> STRING_TO_CLIENT_INFO_CONVERTER = new StringToRedisClientInfoConverter();
static {
STRING_TO_BYTES = new Converter<String, byte[]>() {
@@ -114,6 +121,19 @@ abstract public class JedisConverters extends Converters {
return source == null ? null : SafeEncoder.encode(source);
}
/**
* @param source
* @return
* @since 1.3
*/
public static List<RedisClientInfo> toListOfRedisClientInformation(String source) {
if (!StringUtils.hasText(source)) {
return Collections.emptyList();
}
return STRING_TO_CLIENT_INFO_CONVERTER.convert(source.split("\\r?\\n"));
}
public static DataAccessException toDataAccessException(Exception ex) {
return EXCEPTION_CONVERTER.convert(ex);
}

View File

@@ -43,6 +43,7 @@ import org.springframework.data.redis.connection.RedisConnection;
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.connection.Subscription;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import org.springframework.util.ObjectUtils;
import org.springframework.util.ReflectionUtils;
@@ -1204,4 +1205,8 @@ public class JredisConnection implements RedisConnection {
public String getClientName() {
throw new UnsupportedOperationException("The 'CLIENT GETNAME' command is not supported by the JRedis driver.");
}
public List<RedisClientInfo> getClientList() {
throw new UnsupportedOperationException();
}
}

View File

@@ -49,6 +49,7 @@ import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.connection.Subscription;
import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.TransactionResultConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
@@ -2959,6 +2960,21 @@ public class LettuceConnection implements RedisConnection {
}
}
@Override
public List<RedisClientInfo> getClientList() {
if (isPipelined()) {
throw new UnsupportedOperationException("Cannot be called in pipeline mode.");
}
if (isQueueing()) {
transaction(new LettuceTxResult(getAsyncConnection().clientList(),
LettuceConverters.stringToRedisClientListConverter()));
return null;
}
return LettuceConverters.toListOfRedisClientInformation(getConnection().clientList());
}
/**
* 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

View File

@@ -17,6 +17,7 @@ package org.springframework.data.redis.connection.lettuce;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Date;
import java.util.LinkedHashSet;
import java.util.List;
@@ -31,7 +32,10 @@ import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.connection.SortParameters.Order;
import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import org.springframework.util.StringUtils;
import com.lambdaworks.redis.KeyValue;
import com.lambdaworks.redis.ScoredValue;
@@ -55,6 +59,8 @@ abstract public class LettuceConverters extends Converters {
private static final Converter<ScoredValue<byte[]>, Tuple> SCORED_VALUE_TO_TUPLE;
private static final Converter<Exception, DataAccessException> EXCEPTION_CONVERTER = new LettuceExceptionConverter();
private static final Converter<String[], List<RedisClientInfo>> STRING_TO_LIST_OF_CLIENT_INFO = new StringToRedisClientInfoConverter();
static {
DATE_TO_LONG = new Converter<Date, Long>() {
public Long convert(Date source) {
@@ -115,6 +121,20 @@ abstract public class LettuceConverters extends Converters {
};
}
public static Converter<String, List<RedisClientInfo>> stringToRedisClientListConverter() {
return new Converter<String, List<RedisClientInfo>>() {
@Override
public List<RedisClientInfo> convert(String source) {
if (!StringUtils.hasText(source)) {
return Collections.emptyList();
}
return STRING_TO_LIST_OF_CLIENT_INFO.convert(source.split("\\r?\\n"));
}
};
}
public static Converter<Date, Long> dateToLong() {
return DATE_TO_LONG;
}
@@ -235,4 +255,8 @@ abstract public class LettuceConverters extends Converters {
}
return args;
}
public static List<RedisClientInfo> toListOfRedisClientInformation(String clientList) {
return stringToRedisClientListConverter().convert(clientList);
}
}

View File

@@ -40,6 +40,7 @@ import org.springframework.data.redis.connection.RedisSubscribedConnectionExcept
import org.springframework.data.redis.connection.ReturnType;
import org.springframework.data.redis.connection.SortParameters;
import org.springframework.data.redis.connection.Subscription;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import redis.Command;
@@ -2280,6 +2281,19 @@ public class SrpConnection implements RedisConnection {
}
}
@Override
public List<RedisClientInfo> getClientList() {
if (isQueueing()) {
throw new UnsupportedOperationException();
}
if (isPipelined()) {
pipeline(new SrpGenericResult(pipeline.client_list(), SrpConverters.replyToListOfRedisClientInfo()));
return null;
}
return SrpConverters.toListOfRedisClientInformation(this.client.client_list());
}
private List<Object> closeTransaction() {
List<Object> results = Collections.emptyList();
if (txTracker != null) {

View File

@@ -34,6 +34,8 @@ import org.springframework.data.redis.connection.RedisListCommands.Position;
import org.springframework.data.redis.connection.RedisStringCommands.BitOperation;
import org.springframework.data.redis.connection.RedisZSetCommands.Tuple;
import org.springframework.data.redis.connection.convert.Converters;
import org.springframework.data.redis.connection.convert.StringToRedisClientInfoConverter;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.util.Assert;
import redis.client.RedisException;
@@ -65,8 +67,12 @@ abstract public class SrpConverters extends Converters {
private static final Converter<byte[], String> BYTES_TO_STRING;
private static final Converter<byte[], Double> BYTES_TO_DOUBLE;
private static final Converter<Reply[], Long> REPLIES_TO_TIME_AS_LONG;
private static final Converter<Reply, List<RedisClientInfo>> REPLY_T0_LIST_OF_CLIENT_INFO;
private static final Converter<String[], List<RedisClientInfo>> STRING_TO_LIST_OF_CLIENT_INFO = new StringToRedisClientInfoConverter();
private static final Converter<byte[], List<RedisClientInfo>> BYTEARRAY_T0_LIST_OF_CLIENT_INFO;
static {
REPLIES_TO_BYTES_LIST = new Converter<Reply[], List<byte[]>>() {
public List<byte[]> convert(Reply[] replies) {
if (replies == null) {
@@ -85,21 +91,25 @@ abstract public class SrpConverters extends Converters {
return list;
}
};
REPLIES_TO_BYTES_SET = new Converter<Reply[], Set<byte[]>>() {
public Set<byte[]> convert(Reply[] source) {
return source != null ? new LinkedHashSet<byte[]>(SrpConverters.toBytesList(source)) : null;
}
};
BYTES_TO_PROPERTIES = new Converter<byte[], Properties>() {
public Properties convert(byte[] source) {
return source != null ? SrpConverters.toProperties(new String(source, Charsets.UTF_8)) : null;
}
};
BYTES_TO_DOUBLE = new Converter<byte[], Double>() {
public Double convert(byte[] bytes) {
return (bytes == null || bytes.length == 0 ? null : Double.valueOf(new String(bytes, Charsets.UTF_8)));
}
};
REPLIES_TO_TIME_AS_LONG = new Converter<Reply[], Long>() {
@Override
@@ -115,6 +125,7 @@ abstract public class SrpConverters extends Converters {
}
};
REPLIES_TO_TUPLE_SET = new Converter<Reply[], Set<Tuple>>() {
public Set<Tuple> convert(Reply[] byteArrays) {
if (byteArrays == null) {
@@ -130,6 +141,7 @@ abstract public class SrpConverters extends Converters {
return tuples;
}
};
REPLIES_TO_BYTES_MAP = new Converter<Reply[], Map<byte[], byte[]>>() {
public Map<byte[], byte[]> convert(Reply[] byteArrays) {
if (byteArrays == null) {
@@ -142,11 +154,13 @@ abstract public class SrpConverters extends Converters {
return map;
}
};
BYTES_TO_STRING = new Converter<byte[], String>() {
public String convert(byte[] data) {
return data != null ? new String((byte[]) data, Charsets.UTF_8) : null;
}
};
REPLIES_TO_BOOLEAN_LIST = new Converter<Reply[], List<Boolean>>() {
public List<Boolean> convert(Reply[] source) {
if (source == null) {
@@ -159,6 +173,7 @@ abstract public class SrpConverters extends Converters {
return results;
}
};
REPLIES_TO_STRING_LIST = new Converter<Reply[], List<String>>() {
public List<String> convert(Reply[] source) {
if (source == null) {
@@ -171,6 +186,7 @@ abstract public class SrpConverters extends Converters {
return results;
}
};
REPLY_TO_STRING = new Converter<Reply, String>() {
@Override
@@ -181,6 +197,32 @@ abstract public class SrpConverters extends Converters {
return SrpConverters.toString((byte[]) source.data());
}
};
REPLY_T0_LIST_OF_CLIENT_INFO = new Converter<Reply, List<RedisClientInfo>>() {
@Override
public List<RedisClientInfo> convert(Reply source) {
if (source == null || source.data() == null) {
return Collections.emptyList();
}
Assert.isInstanceOf(byte[].class, source.data(), "Expected data to be an instace of byte [].");
return BYTEARRAY_T0_LIST_OF_CLIENT_INFO.convert((byte[]) source.data());
}
};
BYTEARRAY_T0_LIST_OF_CLIENT_INFO = new Converter<byte[], List<RedisClientInfo>>() {
@Override
public List<RedisClientInfo> convert(byte[] source) {
if (source == null || source.length == 0) {
return Collections.emptyList();
}
String s = SrpConverters.toString(source);
return STRING_TO_LIST_OF_CLIENT_INFO.convert(s.split("\\r?\\n"));
}
};
}
public static Converter<Reply[], List<byte[]>> repliesToBytesList() {
@@ -227,6 +269,10 @@ abstract public class SrpConverters extends Converters {
return REPLIES_TO_TIME_AS_LONG;
}
public static List<RedisClientInfo> toListOfRedisClientInformation(Reply reply) {
return REPLY_T0_LIST_OF_CLIENT_INFO.convert(reply);
}
public static List<byte[]> toBytesList(Reply[] source) {
return REPLIES_TO_BYTES_LIST.convert(source);
}
@@ -312,4 +358,7 @@ abstract public class SrpConverters extends Converters {
return Collections.singletonList(source);
}
public static Converter<byte[], List<RedisClientInfo>> replyToListOfRedisClientInfo() {
return BYTEARRAY_T0_LIST_OF_CLIENT_INFO;
}
}

View File

@@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.springframework.data.redis.connection.DataType;
import org.springframework.data.redis.core.query.SortQuery;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.RedisSerializer;
/**
@@ -174,6 +175,14 @@ public interface RedisOperations<K, V> {
List<Object> exec();
/**
* /** Request information and statistics about connected clients.
*
* @return {@link List} of {@link RedisClientInfo} objects.
* @since 1.3
*/
List<RedisClientInfo> getClientList();
/**
* Execute a transaction, using the provided {@link RedisSerializer} to deserialize any results that are byte[]s or
* Collections of byte[]s. If a result is a Map, the provided {@link RedisSerializer} will be used for both the keys

View File

@@ -40,6 +40,7 @@ import org.springframework.data.redis.core.query.SortQuery;
import org.springframework.data.redis.core.script.DefaultScriptExecutor;
import org.springframework.data.redis.core.script.RedisScript;
import org.springframework.data.redis.core.script.ScriptExecutor;
import org.springframework.data.redis.core.types.RedisClientInfo;
import org.springframework.data.redis.serializer.JdkSerializationRedisSerializer;
import org.springframework.data.redis.serializer.RedisSerializer;
import org.springframework.data.redis.serializer.SerializationUtils;
@@ -1007,4 +1008,15 @@ public class RedisTemplate<K, V> extends RedisAccessor implements RedisOperation
}
});
}
@Override
public List<RedisClientInfo> getClientList() {
return execute(new RedisCallback<List<RedisClientInfo>>() {
@Override
public List<RedisClientInfo> doInRedis(RedisConnection connection) throws DataAccessException {
return connection.getClientList();
}
});
}
}

View File

@@ -0,0 +1,285 @@
/*
* Copyright 2014 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.data.redis.core.types;
import java.io.IOException;
import java.io.StringReader;
import java.util.Properties;
import org.springframework.util.Assert;
/**
* {@link RedisClientInfo} provides general and statistical information about client connections.
*
* @author Christoph Strobl
* @since 1.3
*/
public class RedisClientInfo {
public static enum INFO {
ADDRESS_PORT("addr"), FILE_DESCRIPTOR("fd"), CONNECTION_NAME("name"), CONNECTION_AGE("age"), CONNECTION_IDLE("idle"), FLAGS(
"flags"), DATABSE_ID("db"), CHANNEL_SUBSCRIBTIONS("sub"), PATTERN_SUBSCRIBTIONS("psub"), MULIT_COMMAND_CONTEXT(
"multi"), BUFFER_LENGTH("qbuf"), BUFFER_FREE_SPACE("qbuf-free"), OUTPUT_BUFFER_LENGTH("obl"), OUTPUT_LIST_LENGTH(
"oll"), OUTPUT_BUFFER_MEMORY_USAGE("omem"), EVENTS("events"), LAST_COMMAND("cmd");
String key;
INFO(String key) {
this.key = key;
}
}
private final Properties clientProperties;
public RedisClientInfo(Properties properties) {
Assert.notNull(properties, "Cannot initialize client information for given 'null' properties.");
this.clientProperties = new Properties();
this.clientProperties.putAll(properties);
}
/**
* Get address/port of the client.
*
* @return
*/
public String getAddressPort() {
return get(INFO.ADDRESS_PORT);
}
/**
* Get file descriptor corresponding to the socket
*
* @return
*/
public String getFileDescriptor() {
return get(INFO.FILE_DESCRIPTOR);
}
/**
* Get the clients name.
*
* @return
*/
public String getName() {
return get(INFO.CONNECTION_NAME);
}
/**
* Get total duration of the connection in seconds.
*
* @return
*/
public Long getAge() {
return getLongValueOf(INFO.CONNECTION_AGE);
}
/**
* Get idle time of the connection in seconds.
*
* @return
*/
public Long getIdle() {
return getLongValueOf(INFO.CONNECTION_IDLE);
}
/**
* Get client flags.
*
* @return
*/
public String getFlags() {
return get(INFO.FLAGS);
}
/**
* Get current database index.
*
* @return
*/
public Long getDatabaseId() {
return getLongValueOf(INFO.DATABSE_ID);
}
/**
* Get number of channel subscriptions.
*
* @return
*/
public Long getChannelSubscribtions() {
return getLongValueOf(INFO.CHANNEL_SUBSCRIBTIONS);
}
/**
* Get number of pattern subscriptions.
*
* @return
*/
public Long getPatternSubscrbtions() {
return getLongValueOf(INFO.PATTERN_SUBSCRIBTIONS);
}
/**
* Get the number of commands in a MULTI/EXEC context.
*
* @return
*/
public Long getMultiCommandContext() {
return getLongValueOf(INFO.MULIT_COMMAND_CONTEXT);
}
/**
* Get the query buffer length.
*
* @return
*/
public Long getBufferLength() {
return getLongValueOf(INFO.BUFFER_LENGTH);
}
/**
* Get the free space of the query buffer.
*
* @return
*/
public Long getBufferFreeSpace() {
return getLongValueOf(INFO.BUFFER_FREE_SPACE);
}
/**
* Get the output buffer length.
*
* @return
*/
public Long getOutputBufferLength() {
return getLongValueOf(INFO.OUTPUT_BUFFER_LENGTH);
}
/**
* Get number queued replies in output buffer.
*
* @return
*/
public Long getOutputListLength() {
return getLongValueOf(INFO.OUTPUT_LIST_LENGTH);
}
/**
* Get output buffer memory usage.
*
* @return
*/
public Long getOutputBufferMemoryUsage() {
return getLongValueOf(INFO.OUTPUT_BUFFER_MEMORY_USAGE);
}
/**
* Get file descriptor events.
*
* @return
*/
public String getEvents() {
return get(INFO.EVENTS);
}
/**
* Get last command played.
*
* @return
*/
public String getLastCommand() {
return get(INFO.LAST_COMMAND);
}
/**
* @param info must not be null
* @return {@literal null} if no entry found for requested {@link INFO}.
*/
public String get(INFO info) {
Assert.notNull(info, "Cannot retrieve client information for 'null'.");
return get(info.key);
}
/**
* @param key must not be {@literal null} or {@literal empty}.
* @return {@literal null} if no entry found for requested {@code key}.
*/
public String get(String key) {
Assert.hasText(key, "Cannot get client information for 'empty' / 'null' key.");
return this.clientProperties.getProperty(key);
}
private Long getLongValueOf(INFO info) {
String value = get(info);
return value == null ? null : Long.valueOf(value);
}
@Override
public String toString() {
return this.clientProperties.toString();
}
public static class RedisClientInfoBuilder {
public static RedisClientInfo fromString(String source) {
Assert.notNull(source, "Cannot read client properties form 'null'.");
Properties properties = new Properties();
try {
properties.load(new StringReader(source.replace(' ', '\n')));
} catch (IOException e) {
throw new IllegalArgumentException(String.format("Properties could not be loaded from String '%s'.", source), e);
}
return new RedisClientInfo(properties);
}
}
@Override
public int hashCode() {
final int prime = 31;
int result = 1;
result = prime * result + ((clientProperties == null) ? 0 : clientProperties.hashCode());
return result;
}
@Override
public boolean equals(Object obj) {
if (this == obj) {
return true;
}
if (obj == null) {
return false;
}
if (!(obj instanceof RedisClientInfo)) {
return false;
}
RedisClientInfo other = (RedisClientInfo) obj;
if (clientProperties == null) {
if (other.clientProperties != null) {
return false;
}
} else if (!clientProperties.equals(other.clientProperties)) {
return false;
}
return true;
}
}