Merge branch 'master' into 3.0.0

pull/1303/head
Nikita 8 years ago
commit 5c381654a2

@ -4,6 +4,9 @@ Redisson Releases History
Try __[Redisson PRO](https://redisson.pro)__ version.
### 13-Sep-2017 - versions 2.10.3 and 3.5.3 released
Fixed - ByteBufs are not released properly in SnappyCodec and LZ4Codec (regression since 2.10.2 and 3.5.2)
### 12-Sep-2017 - versions 2.10.2 and 3.5.2 released
Feature - added `addScoreAndGetRank` and `addScoreAndGetRevRank` methods to `RScoredSortedSet` object
Feature - added `addAndGetRank` and `addAndGetRevRank` methods to `RScoredSortedSet` object (thanks to @zuanoc)

@ -6,8 +6,8 @@ Based on high-performance async and lock-free Java Redis client and [Netty](http
| Stable Release Version | JDK Version compatibility | Release Date |
| ------------- | ------------- | ------------|
| 3.5.2 | 1.8+ | 12.09.2017 |
| 2.10.2 | 1.6, 1.7, 1.8 and Android | 12.09.2017 |
| 3.5.3 | 1.8+ | 13.09.2017 |
| 2.10.3 | 1.6, 1.7, 1.8 and Android | 13.09.2017 |
__NOTE__: Both version lines have same features except `CompletionStage` interface added in 3.x.x
@ -67,7 +67,11 @@ Used by
[![Datorama](https://redisson.org/assets/logos/client8.png "Datorama")](https://datorama.com/)    
[![OptionsHouse](https://redisson.org/assets/logos/client9.png "OptionsHouse")](https://www.optionshouse.com/)    
[![Invaluable](https://redisson.org/assets/logos/client13.png "Invaluable")](http://www.invaluable.com/)
[![Ticketmaster](https://redisson.org/assets/logos/client14.png "Ticketmaster")](http://www.ticketmaster.com/)
[![Ticketmaster](https://redisson.org/assets/logos/client14.png "Ticketmaster")](http://www.ticketmaster.com/)   
[![PANDORA](https://redisson.org/assets/logos/client15.png "PANDORA")](http://www.pandora.com/)   
[![ISONAS](https://redisson.org/assets/logos/client16.png "ISONAS")](http://www.isonas.com/)
[![SULAKE](https://redisson.org/assets/logos/client17.png "SULAKE")](http://www.sulake.com/)
Success stories
================================
@ -82,23 +86,23 @@ Quick start
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.5.2</version>
<version>3.5.3</version>
</dependency>
<!-- JDK 1.6+ compatible -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.10.2</version>
<version>2.10.3</version>
</dependency>
#### Gradle
// JDK 1.8+ compatible
compile 'org.redisson:redisson:3.5.2'
compile 'org.redisson:redisson:3.5.3'
// JDK 1.6+ compatible
compile 'org.redisson:redisson:2.10.2'
compile 'org.redisson:redisson:2.10.3'
#### Java
@ -123,11 +127,11 @@ RExecutorService executor = redisson.getExecutorService("myExecutorService");
Downloads
===============================
[Redisson 3.5.2](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.5.2&e=jar),
[Redisson node 3.5.2](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.5.2&e=jar)
[Redisson 3.5.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.5.3&e=jar),
[Redisson node 3.5.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.5.3&e=jar)
[Redisson 2.10.2](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.10.2&e=jar),
[Redisson node 2.10.2](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.10.2&e=jar)
[Redisson 2.10.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.10.3&e=jar),
[Redisson node 2.10.3](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.10.3&e=jar)
### Supported by

@ -27,22 +27,22 @@ Usage
**2** Copy two jars into `TOMCAT_BASE/lib` directory:
1. __For JDK 1.8+__
[redisson-all-3.5.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.5.2&e=jar)
[redisson-all-3.5.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.5.3&e=jar)
for Tomcat 6.x
[redisson-tomcat-6-3.5.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-6&v=3.5.2&e=jar)
[redisson-tomcat-6-3.5.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-6&v=3.5.3&e=jar)
for Tomcat 7.x
[redisson-tomcat-7-3.5.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-7&v=3.5.2&e=jar)
[redisson-tomcat-7-3.5.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-7&v=3.5.3&e=jar)
for Tomcat 8.x
[redisson-tomcat-8-3.5.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-8&v=3.5.2&e=jar)
[redisson-tomcat-8-3.5.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-8&v=3.5.3&e=jar)
2. __For JDK 1.6+__
[redisson-all-2.10.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.10.2&e=jar)
[redisson-all-2.10.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.10.3&e=jar)
for Tomcat 6.x
[redisson-tomcat-6-2.10.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-6&v=2.10.2&e=jar)
[redisson-tomcat-6-2.10.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-6&v=2.10.3&e=jar)
for Tomcat 7.x
[redisson-tomcat-7-2.10.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-7&v=2.10.2&e=jar)
[redisson-tomcat-7-2.10.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-7&v=2.10.3&e=jar)
for Tomcat 8.x
[redisson-tomcat-8-2.10.2.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-8&v=2.10.2&e=jar)
[redisson-tomcat-8-2.10.3.jar](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-tomcat-8&v=2.10.3&e=jar)

@ -113,6 +113,10 @@ public class RedissonSession extends StandardSession {
super.setValid(isValid);
if (map != null) {
if (!isValid && !map.isExists()) {
return;
}
map.fastPut("session:isValid", isValid);
}
}

@ -127,7 +127,7 @@ public class RedissonSessionManager extends ManagerBase implements Lifecycle {
Session result = super.findSession(id);
if (result == null && id != null) {
Map<String, Object> attrs = getMap(id).readAllMap();
if (attrs.isEmpty()) {
if (attrs.isEmpty() || !Boolean.valueOf(String.valueOf(attrs.get("session:isValid")))) {
log.info("Session " + id + " can't be found");
return null;
}

@ -117,6 +117,10 @@ public class RedissonSession extends StandardSession {
super.setValid(isValid);
if (map != null) {
if (!isValid && !map.isExists()) {
return;
}
map.fastPut("session:isValid", isValid);
}
}

@ -105,7 +105,7 @@ public class RedissonSessionManager extends ManagerBase {
Session result = super.findSession(id);
if (result == null && id != null) {
Map<String, Object> attrs = getMap(id).readAllMap();
if (attrs.isEmpty()) {
if (attrs.isEmpty() || !Boolean.valueOf(String.valueOf(attrs.get("session:isValid")))) {
log.info("Session " + id + " can't be found");
return null;
}

@ -118,6 +118,10 @@ public class RedissonSession extends StandardSession {
super.setValid(isValid);
if (map != null) {
if (!isValid && !map.isExists()) {
return;
}
map.fastPut("session:isValid", isValid);
}
}

@ -105,7 +105,8 @@ public class RedissonSessionManager extends ManagerBase {
Session result = super.findSession(id);
if (result == null && id != null) {
Map<String, Object> attrs = getMap(id).readAllMap();
if (attrs.isEmpty()) {
if (attrs.isEmpty() || !Boolean.valueOf(String.valueOf(attrs.get("session:isValid")))) {
log.info("Session " + id + " can't be found");
return null;
}

@ -23,6 +23,7 @@ import java.lang.reflect.Proxy;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.CancellationException;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBlockingQueue;
@ -247,7 +248,11 @@ public abstract class BaseRemoteService {
String canceRequestName = getCancelRequestQueueName(remoteInterface, requestId);
cancelExecution(optionsCopy, responseName, request, mayInterruptIfRunning, canceRequestName, this);
awaitUninterruptibly(60, TimeUnit.SECONDS);
try {
awaitUninterruptibly(60, TimeUnit.SECONDS);
} catch (CancellationException e) {
// skip
}
return isCancelled();
}
};

@ -72,7 +72,6 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.ByteBufAllocator;
import io.netty.buffer.ByteBufUtil;
import io.netty.util.concurrent.FutureListener;
import io.netty.util.internal.PlatformDependent;

@ -321,7 +321,9 @@ public class RedissonKeys implements RKeys {
if (future.isSuccess()) {
List<Long> result = (List<Long>) future.get();
for (Long res : result) {
count.addAndGet(res);
if (res != null) {
count.addAndGet(res);
}
}
} else {
failed.set(future.cause());

@ -112,8 +112,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
private <T> Object generateId(Class<T> entityClass) throws NoSuchFieldException {
String idFieldName = getRIdFieldName(entityClass);
RId annotation = entityClass
.getDeclaredField(idFieldName)
RId annotation = ClassUtils.getDeclaredField(entityClass, idFieldName)
.getAnnotation(RId.class);
Resolver resolver = resolverProvider.getResolver(entityClass,
annotation.generator(), annotation);
@ -182,7 +181,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
throw new IllegalArgumentException("This REntity already exists.");
}
for (FieldDescription.InDefinedShape field : Introspectior.getFieldsDescription(detachedObject.getClass())) {
for (FieldDescription.InDefinedShape field : Introspectior.getAllFields(detachedObject.getClass())) {
Object object = ClassUtils.getField(detachedObject, field.getName());
if (object == null) {
@ -198,7 +197,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
if (rObject instanceof Collection) {
for (Object obj : (Collection<Object>)object) {
if (obj != null && obj.getClass().isAnnotationPresent(REntity.class)) {
if (obj != null && ClassUtils.isAnnotationPresent(obj.getClass(), REntity.class)) {
Object persisted = alreadyPersisted.get(obj);
if (persisted == null) {
if (checkCascade(detachedObject, type, field.getName())) {
@ -216,7 +215,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
Object key = entry.getKey();
Object value = entry.getValue();
if (key != null && key.getClass().isAnnotationPresent(REntity.class)) {
if (key != null && ClassUtils.isAnnotationPresent(key.getClass(), REntity.class)) {
Object persisted = alreadyPersisted.get(key);
if (persisted == null) {
if (checkCascade(detachedObject, type, field.getName())) {
@ -226,7 +225,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
key = persisted;
}
if (value != null && value.getClass().isAnnotationPresent(REntity.class)) {
if (value != null && ClassUtils.isAnnotationPresent(value.getClass(), REntity.class)) {
Object persisted = alreadyPersisted.get(value);
if (persisted == null) {
if (checkCascade(detachedObject, type, field.getName())) {
@ -240,7 +239,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
}
}
excludedFields.add(field.getName());
} else if (object.getClass().isAnnotationPresent(REntity.class)) {
} else if (ClassUtils.isAnnotationPresent(object.getClass(), REntity.class)) {
Object persisted = alreadyPersisted.get(object);
if (persisted == null) {
if (checkCascade(detachedObject, type, field.getName())) {
@ -576,7 +575,7 @@ public class RedissonLiveObjectService implements RLiveObjectService {
if (entityClass.isAnonymousClass() || entityClass.isLocalClass()) {
throw new IllegalArgumentException(entityClass.getName() + " is not publically accessable.");
}
if (!entityClass.isAnnotationPresent(REntity.class)) {
if (!ClassUtils.isAnnotationPresent(entityClass, REntity.class)) {
throw new IllegalArgumentException("REntity annotation is missing from class type declaration.");
}
FieldList<FieldDescription.InDefinedShape> fieldsWithRIdAnnotation
@ -591,11 +590,11 @@ public class RedissonLiveObjectService implements RLiveObjectService {
String idFieldName = idFieldDescription.getName();
Field idField = null;
try {
idField = entityClass.getDeclaredField(idFieldName);
idField = ClassUtils.getDeclaredField(entityClass, idFieldName);
} catch (Exception e) {
throw new IllegalStateException(e);
}
if (idField.getType().isAnnotationPresent(REntity.class)) {
if (ClassUtils.isAnnotationPresent(idField.getType(), REntity.class)) {
throw new IllegalArgumentException("Field with RId annotation cannot be a type of which class is annotated with REntity.");
}
if (idField.getType().isAssignableFrom(RObject.class)) {

@ -86,13 +86,17 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
public RedissonMapCache(EvictionScheduler evictionScheduler, CommandAsyncExecutor commandExecutor,
String name, RedissonClient redisson, MapOptions<K, V> options) {
super(commandExecutor, name, redisson, options);
evictionScheduler.schedule(getName(), getTimeoutSetName(), getIdleSetName(), getExpiredChannelName(), getLastAccessTimeSetName());
if (evictionScheduler != null) {
evictionScheduler.schedule(getName(), getTimeoutSetName(), getIdleSetName(), getExpiredChannelName(), getLastAccessTimeSetName());
}
}
public RedissonMapCache(Codec codec, EvictionScheduler evictionScheduler, CommandAsyncExecutor commandExecutor,
String name, RedissonClient redisson, MapOptions<K, V> options) {
super(codec, commandExecutor, name, redisson, options);
evictionScheduler.schedule(getName(), getTimeoutSetName(), getIdleSetName(), getExpiredChannelName(), getLastAccessTimeSetName());
if (evictionScheduler != null) {
evictionScheduler.schedule(getName(), getTimeoutSetName(), getIdleSetName(), getExpiredChannelName(), getLastAccessTimeSetName());
}
}
@Override

@ -135,10 +135,13 @@ public class RedissonNode {
}
int mapReduceWorkers = config.getMapReduceWorkers();
if (mapReduceWorkers == 0) {
mapReduceWorkers = Runtime.getRuntime().availableProcessors();
if (mapReduceWorkers != -1) {
if (mapReduceWorkers == 0) {
mapReduceWorkers = Runtime.getRuntime().availableProcessors();
}
redisson.getExecutorService(RExecutorService.MAPREDUCE_NAME).registerWorkers(mapReduceWorkers);
log.info("{} map reduce worker(s) registered", mapReduceWorkers);
}
redisson.getExecutorService(RExecutorService.MAPREDUCE_NAME).registerWorkers(mapReduceWorkers);
for (Entry<String, Integer> entry : config.getExecutorServiceWorkers().entrySet()) {
String name = entry.getKey();
@ -192,10 +195,6 @@ public class RedissonNode {
* @return RedissonNode instance
*/
public static RedissonNode create(RedissonNodeConfig config, Redisson redisson) {
if (config.getExecutorServiceWorkers().isEmpty()) {
throw new IllegalArgumentException("Executor service workers are empty");
}
return new RedissonNode(config, redisson);
}

@ -20,6 +20,7 @@ import org.redisson.client.codec.Codec;
import org.redisson.api.RObject;
import org.redisson.api.RObjectReactive;
import org.redisson.api.annotation.REntity;
import org.redisson.liveobject.misc.ClassUtils;
import org.redisson.misc.BiHashMap;
import org.redisson.reactive.RedissonAtomicLongReactive;
import org.redisson.reactive.RedissonBitSetReactive;
@ -77,7 +78,7 @@ public class RedissonReference implements Serializable {
}
public RedissonReference(Class type, String keyName, Codec codec) {
if (!type.isAnnotationPresent(REntity.class) && !RObject.class.isAssignableFrom(type) && !RObjectReactive.class.isAssignableFrom(type)) {
if (!ClassUtils.isAnnotationPresent(type, REntity.class) && !RObject.class.isAssignableFrom(type) && !RObjectReactive.class.isAssignableFrom(type)) {
throw new IllegalArgumentException("Class reference has to be a type of either RObject or RLiveObject or RObjectReactive");
}
this.type = RObjectReactive.class.isAssignableFrom(type)
@ -130,7 +131,7 @@ public class RedissonReference implements Serializable {
* @param type the type to set
*/
public void setType(Class<?> type) {
if (!type.isAnnotationPresent(REntity.class) && (!RObject.class.isAssignableFrom(type) || !RObjectReactive.class.isAssignableFrom(type))) {
if (!ClassUtils.isAnnotationPresent(type, REntity.class) && (!RObject.class.isAssignableFrom(type) || !RObjectReactive.class.isAssignableFrom(type))) {
throw new IllegalArgumentException("Class reference has to be a type of either RObject or RLiveObject or RObjectReactive");
}
this.type = type.getName();

@ -24,6 +24,10 @@ public class WriteRedisConnectionException extends RedisException {
private static final long serialVersionUID = -4756928186967834601L;
public WriteRedisConnectionException(String msg) {
super(msg);
}
public WriteRedisConnectionException(String msg, Throwable e) {
super(msg, e);
}

@ -19,8 +19,9 @@ import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.CommandsData;
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelHandler.Sharable;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelPromise;
import io.netty.handler.codec.MessageToByteEncoder;
/**
@ -32,6 +33,17 @@ import io.netty.handler.codec.MessageToByteEncoder;
public class CommandBatchEncoder extends MessageToByteEncoder<CommandsData> {
public static final CommandBatchEncoder INSTANCE = new CommandBatchEncoder();
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (acceptOutboundMessage(msg)) {
if (!promise.setUncancellable()) {
return;
}
}
super.write(ctx, msg, promise);
}
@Override
protected void encode(ChannelHandlerContext ctx, CommandsData msg, ByteBuf out) throws Exception {

@ -59,6 +59,12 @@ public class CommandEncoder extends MessageToByteEncoder<CommandData<?, ?>> {
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (acceptOutboundMessage(msg)) {
if (!promise.setUncancellable()) {
return;
}
}
try {
super.write(ctx, msg, promise);
} catch (Exception e) {

@ -20,6 +20,7 @@ import java.util.List;
import java.util.Queue;
import java.util.regex.Pattern;
import org.redisson.client.WriteRedisConnectionException;
import org.redisson.client.protocol.CommandData;
import org.redisson.client.protocol.QueueCommand;
import org.redisson.client.protocol.QueueCommandHolder;
@ -27,10 +28,10 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import io.netty.channel.Channel;
import io.netty.channel.ChannelDuplexHandler;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOutboundHandlerAdapter;
import io.netty.channel.ChannelPromise;
import io.netty.util.AttributeKey;
import io.netty.util.internal.PlatformDependent;
@ -41,7 +42,7 @@ import io.netty.util.internal.PlatformDependent;
* @author Nikita Koksharov
*
*/
public class CommandsQueue extends ChannelOutboundHandlerAdapter {
public class CommandsQueue extends ChannelDuplexHandler {
private static final Logger log = LoggerFactory.getLogger(CommandsQueue.class);
@ -52,10 +53,12 @@ public class CommandsQueue extends ChannelOutboundHandlerAdapter {
private final Queue<QueueCommandHolder> queue = PlatformDependent.newMpscQueue();
private volatile boolean isInactive;
private final ChannelFutureListener listener = new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
if (!future.isSuccess()) {
if (!future.isSuccess() && !isInactive) {
sendNextCommand(future.channel());
}
}
@ -67,6 +70,22 @@ public class CommandsQueue extends ChannelOutboundHandlerAdapter {
sendData(channel);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
isInactive = true;
while (true) {
QueueCommandHolder command = queue.poll();
if (command == null) {
break;
}
command.getChannelPromise().tryFailure(
new WriteRedisConnectionException("Can't write command: " + command.getCommand() + " to channel: " + ctx.channel()));
}
super.channelInactive(ctx);
}
@Override
public void write(ChannelHandlerContext ctx, Object msg, ChannelPromise promise) throws Exception {
if (msg instanceof QueueCommand) {

@ -21,6 +21,7 @@ import org.redisson.client.codec.Codec;
import org.redisson.api.RObject;
import org.redisson.api.annotation.REntity;
import org.redisson.api.annotation.RObjectField;
import org.redisson.liveobject.misc.ClassUtils;
/**
*
@ -44,7 +45,7 @@ public class DefaultCodecProvider implements CodecProvider {
@Override
public <T extends Codec> T getCodec(REntity anno, Class<?> cls) {
if (!cls.isAnnotationPresent(anno.annotationType())) {
if (!ClassUtils.isAnnotationPresent(cls, anno.annotationType())) {
throw new IllegalArgumentException("Annotation REntity does not present on type [" + cls.getCanonicalName() + "]");
}
return this.<T>getCodec((Class<T>) anno.codec());
@ -53,7 +54,7 @@ public class DefaultCodecProvider implements CodecProvider {
@Override
public <T extends Codec, K extends RObject> T getCodec(RObjectField anno, Class<?> cls, Class<K> rObjectClass, String fieldName) {
try {
if (!cls.getField(fieldName).isAnnotationPresent(anno.getClass())) {
if (!ClassUtils.getDeclaredField(cls, fieldName).isAnnotationPresent(anno.getClass())) {
throw new IllegalArgumentException("Annotation RObjectField does not present on field " + fieldName + " of type [" + cls.getCanonicalName() + "]");
}
} catch (Exception ex) {

@ -71,6 +71,9 @@ import io.netty.util.Timeout;
import io.netty.util.TimerTask;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.FutureListener;
import java.util.AbstractMap;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
/**
*
@ -111,17 +114,17 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
return this;
}
@Override
public boolean isRedissonReferenceSupportEnabled() {
return redisson != null || redissonReactive != null;
}
@Override
public void syncSubscription(RFuture<?> future) {
MasterSlaveServersConfig config = connectionManager.getConfig();
try {
int timeout = config.getTimeout() + config.getRetryInterval()*config.getRetryAttempts();
int timeout = config.getTimeout() + config.getRetryInterval() * config.getRetryAttempts();
if (!future.await(timeout)) {
throw new RedisTimeoutException("Subscribe timeout: (" + timeout + "ms)");
}
@ -130,7 +133,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
future.syncUninterruptibly();
}
@Override
public <V> V get(RFuture<V> future) {
if (!future.isDone()) {
@ -141,7 +144,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
l.countDown();
}
});
boolean interrupted = false;
while (!future.isDone()) {
try {
@ -150,7 +153,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
interrupted = true;
}
}
if (interrupted) {
Thread.currentThread().interrupt();
}
@ -176,16 +179,16 @@ public class CommandAsyncService implements CommandAsyncExecutor {
});
return l.await(timeout, timeoutUnit);
}
@Override
public <T, R> RFuture<R> readAsync(InetSocketAddress client, MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(InetSocketAddress client, MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
async(true, new NodeSource(entry, client), codec, command, params, mainPromise, 0);
return mainPromise;
}
@Override
public <T, R> RFuture<R> readAsync(InetSocketAddress client, String key, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(InetSocketAddress client, String key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
int slot = connectionManager.calcSlot(key);
async(true, new NodeSource(slot, client), codec, command, params, mainPromise, 0);
@ -193,7 +196,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public <T, R> RFuture<Collection<R>> readAllAsync(RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<Collection<R>> readAllAsync(RedisCommand<T> command, Object... params) {
final RPromise<Collection<R>> mainPromise = connectionManager.newPromise();
final Set<MasterSlaveEntry> nodes = connectionManager.getEntrySet();
final List<R> results = new ArrayList<R>();
@ -205,18 +208,18 @@ public class CommandAsyncService implements CommandAsyncExecutor {
mainPromise.tryFailure(future.cause());
return;
}
R result = future.getNow();
if (result instanceof Collection) {
synchronized (results) {
results.addAll((Collection)result);
results.addAll((Collection) result);
}
} else {
synchronized (results) {
results.add(result);
}
}
if (counter.decrementAndGet() == 0
&& !mainPromise.isDone()) {
mainPromise.trySuccess(results);
@ -233,7 +236,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public <T, R> RFuture<R> readRandomAsync(RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readRandomAsync(RedisCommand<T> command, Object... params) {
final RPromise<R> mainPromise = connectionManager.newPromise();
final List<MasterSlaveEntry> nodes = new ArrayList<MasterSlaveEntry>(connectionManager.getEntrySet());
Collections.shuffle(nodes);
@ -269,21 +272,21 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public <T> RFuture<Void> writeAllAsync(RedisCommand<T> command, Object ... params) {
public <T> RFuture<Void> writeAllAsync(RedisCommand<T> command, Object... params) {
return writeAllAsync(command, null, params);
}
@Override
public <R, T> RFuture<R> writeAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, Object ... params) {
public <R, T> RFuture<R> writeAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, Object... params) {
return allAsync(false, command, callback, params);
}
@Override
public <R, T> RFuture<R> readAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, Object ... params) {
public <R, T> RFuture<R> readAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, Object... params) {
return allAsync(true, command, callback, params);
}
private <T, R> RFuture<R> allAsync(boolean readOnlyMode, RedisCommand<T> command, final SlotCallback<T, R> callback, Object ... params) {
private <T, R> RFuture<R> allAsync(boolean readOnlyMode, RedisCommand<T> command, final SlotCallback<T, R> callback, Object... params) {
final RPromise<R> mainPromise = connectionManager.newPromise();
final Set<MasterSlaveEntry> nodes = connectionManager.getEntrySet();
final AtomicInteger counter = new AtomicInteger(nodes.size());
@ -317,9 +320,9 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
public <V> RedisException convertException(RFuture<V> future) {
return future.cause() instanceof RedisException ?
(RedisException) future.cause() :
new RedisException("Unexpected exception while processing command", future.cause());
return future.cause() instanceof RedisException
? (RedisException) future.cause()
: new RedisException("Unexpected exception while processing command", future.cause());
}
private NodeSource getNodeSource(String key) {
@ -329,88 +332,86 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public <T, R> RFuture<R> readAsync(String key, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(String key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
NodeSource source = getNodeSource(key);
async(true, source, codec, command, params, mainPromise, 0);
return mainPromise;
}
public <T, R> RFuture<R> readAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
async(true, new NodeSource(entry), codec, command, params, mainPromise, 0);
return mainPromise;
}
public <T, R> RFuture<R> readAsync(Integer slot, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(Integer slot, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
async(true, new NodeSource(slot), codec, command, params, mainPromise, 0);
return mainPromise;
}
@Override
public <T, R> RFuture<R> writeAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> writeAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
async(false, new NodeSource(entry), codec, command, params, mainPromise, 0);
return mainPromise;
}
@Override
public <T, R> RFuture<R> writeAsync(Integer slot, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> writeAsync(Integer slot, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
async(false, new NodeSource(slot), codec, command, params, mainPromise, 0);
return mainPromise;
}
@Override
public <T, R> RFuture<R> readAsync(String key, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> readAsync(String key, RedisCommand<T> command, Object... params) {
return readAsync(key, connectionManager.getCodec(), command, params);
}
@Override
public <T, R> RFuture<R> evalReadAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalReadAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
NodeSource source = getNodeSource(key);
return evalAsync(source, true, codec, evalCommandType, script, keys, params);
}
@Override
public <T, R> RFuture<R> evalReadAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalReadAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
return evalAsync(new NodeSource(entry), true, codec, evalCommandType, script, keys, params);
}
@Override
public <T, R> RFuture<R> evalReadAsync(Integer slot, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalReadAsync(Integer slot, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
return evalAsync(new NodeSource(slot), true, codec, evalCommandType, script, keys, params);
}
@Override
public <T, R> RFuture<R> evalReadAsync(InetSocketAddress client, String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalReadAsync(InetSocketAddress client, String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
int slot = connectionManager.calcSlot(key);
return evalAsync(new NodeSource(slot, client), true, codec, evalCommandType, script, keys, params);
}
@Override
public <T, R> RFuture<R> evalWriteAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalWriteAsync(String key, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
NodeSource source = getNodeSource(key);
return evalAsync(source, false, codec, evalCommandType, script, keys, params);
}
public <T, R> RFuture<R> evalWriteAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalWriteAsync(MasterSlaveEntry entry, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
return evalAsync(new NodeSource(entry), false, codec, evalCommandType, script, keys, params);
}
public <T, R> RFuture<R> evalWriteAsync(Integer slot, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalWriteAsync(Integer slot, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
return evalAsync(new NodeSource(slot), false, codec, evalCommandType, script, keys, params);
}
@Override
public <T, R> RFuture<R> evalWriteAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalWriteAllAsync(RedisCommand<T> command, SlotCallback<T, R> callback, String script, List<Object> keys, Object... params) {
return evalAllAsync(false, command, callback, script, keys, params);
}
public <T, R> RFuture<R> evalAllAsync(boolean readOnlyMode, RedisCommand<T> command, final SlotCallback<T, R> callback, String script, List<Object> keys, Object ... params) {
public <T, R> RFuture<R> evalAllAsync(boolean readOnlyMode, RedisCommand<T> command, final SlotCallback<T, R> callback, String script, List<Object> keys, Object... params) {
final RPromise<R> mainPromise = connectionManager.newPromise();
final Set<MasterSlaveEntry> entries = connectionManager.getEntrySet();
final AtomicInteger counter = new AtomicInteger(entries.size());
@ -425,7 +426,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
callback.onSlotResult(future.getNow());
if (counter.decrementAndGet() == 0
&& !mainPromise.isDone()) {
&& !mainPromise.isDone()) {
mainPromise.trySuccess(callback.onFinish());
}
}
@ -444,7 +445,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
return mainPromise;
}
private <T, R> RFuture<R> evalAsync(NodeSource nodeSource, boolean readOnlyMode, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object ... params) {
private <T, R> RFuture<R> evalAsync(NodeSource nodeSource, boolean readOnlyMode, Codec codec, RedisCommand<T> evalCommandType, String script, List<Object> keys, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
List<Object> args = new ArrayList<Object>(2 + keys.size() + params.length);
args.add(script);
@ -456,12 +457,12 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
@Override
public <T, R> RFuture<R> writeAsync(String key, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> writeAsync(String key, RedisCommand<T> command, Object... params) {
return writeAsync(key, connectionManager.getCodec(), command, params);
}
@Override
public <T, R> RFuture<R> writeAsync(String key, Codec codec, RedisCommand<T> command, Object ... params) {
public <T, R> RFuture<R> writeAsync(String key, Codec codec, RedisCommand<T> command, Object... params) {
RPromise<R> mainPromise = connectionManager.newPromise();
NodeSource source = getNodeSource(key);
async(false, source, codec, command, params, mainPromise, 0);
@ -469,7 +470,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
protected <V, R> void async(final boolean readOnlyMode, final NodeSource source, final Codec codec,
final RedisCommand<V> command, final Object[] params, final RPromise<R> mainPromise, final int attempt) {
final RedisCommand<V> command, final Object[] params, final RPromise<R> mainPromise, final int attempt) {
if (mainPromise.isCancelled()) {
free(params);
return;
@ -481,7 +482,6 @@ public class CommandAsyncService implements CommandAsyncExecutor {
return;
}
final AsyncDetails<V, R> details = AsyncDetails.acquire();
if (isRedissonReferenceSupportEnabled()) {
try {
@ -522,7 +522,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
}
};
final TimerTask retryTimerTask = new TimerTask() {
@Override
@ -539,7 +539,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
if (details.getAttempt() == connectionManager.getConfig().getRetryAttempts()) {
if (details.getWriteFuture().cancel(false)) {
if (details.getException() == null) {
details.setException(new RedisTimeoutException("Unable to send command: " + command + " with params: " + LogHelper.toString(details.getParams() + " after " + connectionManager.getConfig().getRetryAttempts() + " retry attempts")));
details.setException(new RedisTimeoutException("Unable to send command: " + command + " with params: " + LogHelper.toString(details.getParams()) + " after " + connectionManager.getConfig().getRetryAttempts() + " retry attempts"));
}
details.getAttemptPromise().tryFailure(details.getException());
}
@ -550,7 +550,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
details.setTimeout(timeout);
return;
}
if (details.getWriteFuture().isDone() && details.getWriteFuture().isSuccess()) {
return;
}
@ -591,30 +591,30 @@ public class CommandAsyncService implements CommandAsyncExecutor {
Timeout timeout = connectionManager.newTimeout(retryTimerTask, connectionManager.getConfig().getRetryInterval(), TimeUnit.MILLISECONDS);
details.setTimeout(timeout);
details.setupMainPromiseListener(mainPromiseListener);
connectionFuture.addListener(new FutureListener<RedisConnection>() {
@Override
public void operationComplete(Future<RedisConnection> connFuture) throws Exception {
if (connFuture.isCancelled()) {
return;
}
if (!connFuture.isSuccess()) {
connectionManager.getShutdownLatch().release();
details.setException(convertException(connectionFuture));
return;
}
if (details.getAttemptPromise().isDone() || details.getMainPromise().isDone()) {
releaseConnection(source, connectionFuture, details.isReadOnlyMode(), details.getAttemptPromise(), details);
return;
}
final RedisConnection connection = connFuture.getNow();
if (details.getSource().getRedirect() == Redirect.ASK) {
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(2);
RPromise<Void> promise = connectionManager.newPromise();
list.add(new CommandData<Void, Void>(promise, details.getCodec(), RedisCommands.ASKING, new Object[] {}));
list.add(new CommandData<Void, Void>(promise, details.getCodec(), RedisCommands.ASKING, new Object[]{}));
list.add(new CommandData<V, R>(details.getAttemptPromise(), details.getCodec(), details.getCommand(), details.getParams()));
RPromise<Void> main = connectionManager.newPromise();
ChannelFuture future = connection.send(new CommandsData(main, list));
@ -627,7 +627,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
ChannelFuture future = connection.send(new CommandData<V, R>(details.getAttemptPromise(), details.getCodec(), details.getCommand(), details.getParams()));
details.setWriteFuture(future);
}
details.getWriteFuture().addListener(new ChannelFutureListener() {
@Override
public void operationComplete(ChannelFuture future) throws Exception {
@ -658,26 +658,25 @@ public class CommandAsyncService implements CommandAsyncExecutor {
ReferenceCountUtil.safeRelease(obj);
}
}
private <V, R> void checkWriteFuture(final AsyncDetails<V, R> details, final RedisConnection connection) {
ChannelFuture future = details.getWriteFuture();
if (details.getAttemptPromise().isDone()) {
if (future.isCancelled() || details.getAttemptPromise().isDone()) {
return;
}
if (!future.isSuccess()) {
log.trace("Can't write {} to {}", details.getCommand(), connection);
details.setException(new WriteRedisConnectionException(
"Can't write command: " + details.getCommand() + ", params: " + LogHelper.toString(details.getParams()) + " to channel: " + future.channel(), future.cause()));
if (details.getAttempt() == connectionManager.getConfig().getRetryAttempts()) {
details.getAttemptPromise().tryFailure(details.getException());
free(details);
}
return;
}
details.getTimeout().cancel();
long timeoutTime = connectionManager.getConfig().getTimeout();
if (RedisCommands.BLOCKING_COMMANDS.contains(details.getCommand().getName())) {
Long popTimeout = Long.valueOf(details.getParams()[details.getParams().length - 1].toString());
@ -685,7 +684,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
if (popTimeout == 0) {
return;
}
timeoutTime += popTimeout*1000;
timeoutTime += popTimeout * 1000;
// add 1 second due to issue https://github.com/antirez/redis/issues/874
timeoutTime += 1000;
}
@ -711,7 +710,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
details.getMainPromise().tryFailure(new RedissonShutdownException("Redisson is shutdown"));
}
};
final Timeout scheduledFuture;
if (popTimeout != 0) {
// to handle cases when connection has been lost
@ -721,11 +720,11 @@ public class CommandAsyncService implements CommandAsyncExecutor {
public void run(Timeout timeout) throws Exception {
// re-connection hasn't been made
// and connection is still active
if (orignalChannel == connection.getChannel()
if (orignalChannel == connection.getChannel()
&& connection.isActive()) {
return;
}
if (details.getAttemptPromise().trySuccess(null)) {
connection.forceFastReconnectAsync();
}
@ -734,7 +733,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
} else {
scheduledFuture = null;
}
details.getMainPromise().addListener(new FutureListener<R>() {
@Override
public void operationComplete(Future<R> future) throws Exception {
@ -757,13 +756,13 @@ public class CommandAsyncService implements CommandAsyncExecutor {
});
return;
}
if (future.cause() instanceof RedissonShutdownException) {
details.getAttemptPromise().tryFailure(future.cause());
}
}
});
synchronized (listener) {
if (!details.getMainPromise().isDone()) {
connectionManager.getShutdownPromise().addListener(listener);
@ -772,14 +771,14 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
protected <V, R> void releaseConnection(final NodeSource source, final RFuture<RedisConnection> connectionFuture,
final boolean isReadOnly, RPromise<R> attemptPromise, final AsyncDetails<V, R> details) {
final boolean isReadOnly, RPromise<R> attemptPromise, final AsyncDetails<V, R> details) {
attemptPromise.addListener(new FutureListener<R>() {
@Override
public void operationComplete(Future<R> future) throws Exception {
if (!connectionFuture.isSuccess()) {
return;
}
RedisConnection connection = connectionFuture.getNow();
connectionManager.getShutdownLatch().release();
if (isReadOnly) {
@ -787,7 +786,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
} else {
connectionManager.releaseWrite(source, connection);
}
if (log.isDebugEnabled()) {
log.debug("connection released for command {} and params {} from slot {} using connection {}",
details.getCommand(), Arrays.toString(details.getParams()), details.getSource(), connection);
@ -806,7 +805,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
details.removeMainPromiseListener();
if (future.cause() instanceof RedisMovedException) {
RedisMovedException ex = (RedisMovedException)future.cause();
RedisMovedException ex = (RedisMovedException) future.cause();
async(details.isReadOnlyMode(), new NodeSource(ex.getSlot(), ex.getAddr(), Redirect.MOVED), details.getCodec(),
details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt());
AsyncDetails.release(details);
@ -814,7 +813,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
if (future.cause() instanceof RedisAskException) {
RedisAskException ex = (RedisAskException)future.cause();
RedisAskException ex = (RedisAskException) future.cause();
async(details.isReadOnlyMode(), new NodeSource(ex.getSlot(), ex.getAddr(), Redirect.ASK), details.getCodec(),
details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt());
AsyncDetails.release(details);
@ -827,14 +826,14 @@ public class CommandAsyncService implements CommandAsyncExecutor {
AsyncDetails.release(details);
return;
}
if (future.cause() instanceof RedisTryAgainException) {
connectionManager.newTimeout(new TimerTask() {
@Override
public void run(Timeout timeout) throws Exception {
async(details.isReadOnlyMode(), source, details.getCodec(),
details.getCommand(), details.getParams(), details.getMainPromise(), details.getAttempt());
}
}, 1, TimeUnit.SECONDS);
AsyncDetails.release(details);
@ -842,7 +841,7 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
free(details);
if (future.isSuccess()) {
R res = future.getNow();
if (res instanceof RedisClientResult) {
@ -850,9 +849,9 @@ public class CommandAsyncService implements CommandAsyncExecutor {
if (addr == null) {
addr = details.getConnectionFuture().getNow().getRedisClient().getAddr();
}
((RedisClientResult)res).setRedisClient(addr);
((RedisClientResult) res).setRedisClient(addr);
}
if (isRedissonReferenceSupportEnabled()) {
handleReference(details.getMainPromise(), res);
} else {
@ -867,29 +866,60 @@ public class CommandAsyncService implements CommandAsyncExecutor {
private <R, V> void handleReference(RPromise<R> mainPromise, R res) {
if (res instanceof List) {
List<Object> r = (List<Object>)res;
List<Object> r = (List<Object>) res;
for (int i = 0; i < r.size(); i++) {
if (r.get(i) instanceof RedissonReference) {
try {
r.set(i, redisson != null
? RedissonObjectFactory.fromReference(redisson, (RedissonReference) r.get(i))
: RedissonObjectFactory.fromReference(redissonReactive, (RedissonReference) r.get(i)));
} catch (Exception exception) {//skip and carry on to next one.
}
r.set(i, fromReference(r.get(i)));
} else if (r.get(i) instanceof ScoredEntry && ((ScoredEntry) r.get(i)).getValue() instanceof RedissonReference) {
try {
ScoredEntry<?> se = ((ScoredEntry<?>) r.get(i));
se = new ScoredEntry(se.getScore(), redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) se.getValue())
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) se.getValue()));
r.set(i, se);
} catch (Exception exception) {//skip and carry on to next one.
}
ScoredEntry<?> se = ((ScoredEntry<?>) r.get(i));
se = new ScoredEntry(se.getScore(), fromReference(se.getValue()));
r.set(i, se);
}
}
mainPromise.trySuccess(res);
} else if (res instanceof Set) {
Set r = (Set) res;
LinkedHashSet converted = new LinkedHashSet();
for (Object o : r) {
if (o instanceof RedissonReference) {
converted.add(fromReference(o));
} else if (o instanceof ScoredEntry && ((ScoredEntry) o).getValue() instanceof RedissonReference) {
ScoredEntry<?> se = ((ScoredEntry<?>) o);
se = new ScoredEntry(se.getScore(), fromReference(se.getValue()));
converted.add(se);
} else if (o instanceof Map.Entry) {
Map.Entry old = (Map.Entry) o;
Object key = old.getKey();
if (key instanceof RedissonReference) {
key = fromReference(key);
}
Object value = old.getValue();
if (value instanceof RedissonReference) {
value = fromReference(value);
}
converted.add(new AbstractMap.SimpleEntry(key, value));
} else {
converted.add(o);
}
}
mainPromise.trySuccess((R) converted);
} else if (res instanceof Map) {
Map<Object, Object> map = (Map<Object, Object>) res;
LinkedHashMap<Object, Object> converted = new LinkedHashMap<Object, Object>();
for (Map.Entry<Object, Object> e : map.entrySet()) {
Object value = e.getValue();
if (e.getValue() instanceof RedissonReference) {
value = fromReference(e.getValue());
}
Object key = e.getKey();
if (e.getKey() instanceof RedissonReference) {
key = fromReference(e.getKey());
}
converted.put(key, value);
}
mainPromise.trySuccess((R) converted);
} else if (res instanceof ListScanResult) {
List<ScanObjectEntry> r = ((ListScanResult)res).getValues();
List<ScanObjectEntry> r = ((ListScanResult) res).getValues();
for (int i = 0; i < r.size(); i++) {
Object obj = r.get(i);
if (!(obj instanceof ScanObjectEntry)) {
@ -897,60 +927,42 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
ScanObjectEntry e = r.get(i);
if (e.getObj() instanceof RedissonReference) {
try {
r.set(i , new ScanObjectEntry(e.getBuf(), redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) e.getObj())
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) e.getObj())));
} catch (Exception exception) {//skip and carry on to next one.
}
r.set(i, new ScanObjectEntry(e.getBuf(), fromReference(e.getObj())));
} else if (e.getObj() instanceof ScoredEntry && ((ScoredEntry<?>) e.getObj()).getValue() instanceof RedissonReference) {
try {
ScoredEntry<?> se = ((ScoredEntry<?>) e.getObj());
se = new ScoredEntry(se.getScore(), redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) se.getValue())
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) se.getValue()));
r.set(i, new ScanObjectEntry(e.getBuf(), se));
} catch (Exception exception) {//skip and carry on to next one.
}
ScoredEntry<?> se = ((ScoredEntry<?>) e.getObj());
se = new ScoredEntry(se.getScore(), fromReference(se.getValue()));
r.set(i, new ScanObjectEntry(e.getBuf(), se));
}
}
mainPromise.trySuccess(res);
} else if (res instanceof MapScanResult) {
Map<ScanObjectEntry, ScanObjectEntry> map = ((MapScanResult)res).getMap();
HashMap<ScanObjectEntry, ScanObjectEntry> toAdd = null;
for (Map.Entry<ScanObjectEntry, ScanObjectEntry> e : map.entrySet()) {
MapScanResult scanResult = (MapScanResult) res;
Map<ScanObjectEntry, ScanObjectEntry> map = ((MapScanResult) res).getMap();
LinkedHashMap<ScanObjectEntry, ScanObjectEntry> converted = new LinkedHashMap<ScanObjectEntry, ScanObjectEntry>();
boolean hasConversion = false;
for (Map.Entry<ScanObjectEntry, ScanObjectEntry> e : map.entrySet()) {
ScanObjectEntry value = e.getValue();
if (e.getValue().getObj() instanceof RedissonReference) {
try {
e.setValue(new ScanObjectEntry(e.getValue().getBuf(), redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) e.getValue().getObj())
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) e.getValue().getObj())));
} catch (Exception exception) {//skip and carry on to next one.
}
value = new ScanObjectEntry(e.getValue().getBuf(), fromReference(e.getValue().getObj()));
hasConversion = true;
}
ScanObjectEntry key = e.getKey();
if (e.getKey().getObj() instanceof RedissonReference) {
if (toAdd == null) {
toAdd = new HashMap<ScanObjectEntry, ScanObjectEntry>();
}
toAdd.put(e.getKey(), e.getValue());
key = new ScanObjectEntry(e.getKey().getBuf(), fromReference(e.getKey().getObj()));
hasConversion = true;
}
converted.put(key, value);
}
if (toAdd != null) {
for (Map.Entry<ScanObjectEntry, ScanObjectEntry> e : toAdd.entrySet()) {
try {
map.put(new ScanObjectEntry(e.getValue().getBuf(), (redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) e.getKey().getObj())
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) e.getKey().getObj()))), map.remove(e.getKey()));
} catch (Exception exception) {//skip and carry on to next one.
}
}
if (hasConversion) {
MapScanResult<ScanObjectEntry, ScanObjectEntry> newScanResult = new MapScanResult<ScanObjectEntry, ScanObjectEntry>(scanResult.getPos(), converted);
newScanResult.setRedisClient(scanResult.getRedisClient());
mainPromise.trySuccess((R) newScanResult);
} else {
mainPromise.trySuccess((R) res);
}
mainPromise.trySuccess(res);
} else if (res instanceof RedissonReference) {
try {
mainPromise.trySuccess(redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) res)
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) res));
mainPromise.trySuccess(this.<R>fromReference(res));
} catch (Exception exception) {
mainPromise.trySuccess(res);//fallback
}
@ -959,4 +971,13 @@ public class CommandAsyncService implements CommandAsyncExecutor {
}
}
private <R> R fromReference(Object res) {
try {
return redisson != null
? RedissonObjectFactory.<R>fromReference(redisson, (RedissonReference) res)
: RedissonObjectFactory.<R>fromReference(redissonReactive, (RedissonReference) res);
} catch (Exception exception) {
return (R) res;
}
}
}

@ -45,7 +45,6 @@ import org.redisson.connection.ConnectionManager;
import org.redisson.connection.MasterSlaveEntry;
import org.redisson.connection.NodeSource;
import org.redisson.connection.NodeSource.Redirect;
import org.redisson.misc.LogHelper;
import org.redisson.misc.RPromise;
import org.redisson.misc.RedissonObjectFactory;
@ -277,7 +276,7 @@ public class CommandBatchService extends CommandAsyncService {
if (future.isCancelled() && connectionFuture.cancel(false)) {
log.debug("Connection obtaining canceled for batch");
details.getTimeout().cancel();
if (details.getAttemptPromise().cancel(false)) {
if (attemptPromise.cancel(false)) {
free(entry);
}
}
@ -301,7 +300,7 @@ public class CommandBatchService extends CommandAsyncService {
if (details.getException() == null) {
details.setException(new RedisTimeoutException("Unable to send batch after " + connectionManager.getConfig().getRetryAttempts() + " retry attempts"));
}
details.getAttemptPromise().tryFailure(details.getException());
attemptPromise.tryFailure(details.getException());
}
return;
}
@ -418,11 +417,14 @@ public class CommandBatchService extends CommandAsyncService {
private void checkWriteFuture(Entry entry, final RPromise<Void> attemptPromise, AsyncDetails details,
final RedisConnection connection, ChannelFuture future, boolean noResult, long responseTimeout, int attempts) {
if (future.isCancelled() || attemptPromise.isDone()) {
return;
}
if (!future.isSuccess()) {
details.setException(new WriteRedisConnectionException("Can't write command batch to channel: " + future.channel(), future.cause()));
if (details.getAttempt() == attempts) {
details.getAttemptPromise().tryFailure(details.getException());
free(entry);
attemptPromise.tryFailure(details.getException());
}
return;
}
@ -448,7 +450,7 @@ public class CommandBatchService extends CommandAsyncService {
private void checkConnectionFuture(final Entry entry, final NodeSource source,
final RPromise<Void> mainPromise, final RPromise<Void> attemptPromise, final AsyncDetails details,
RFuture<RedisConnection> connFuture, final boolean noResult, final long responseTimeout, final int attempts) {
if (attemptPromise.isDone() || mainPromise.isCancelled() || connFuture.isCancelled()) {
if (connFuture.isCancelled()) {
return;
}
@ -458,6 +460,11 @@ public class CommandBatchService extends CommandAsyncService {
return;
}
if (attemptPromise.isDone() || mainPromise.isDone()) {
releaseConnection(source, connFuture, details.isReadOnlyMode(), attemptPromise, details);
return;
}
final RedisConnection connection = connFuture.getNow();
List<CommandData<?, ?>> list = new ArrayList<CommandData<?, ?>>(entry.getCommands().size() + 1);

@ -50,7 +50,11 @@ public class RedissonNodeConfig extends Config {
/**
* MapReduce workers amount.
* 0 = current_processors_amount
* <p>
* <code>0 = current_processors_amount</code>
* <p>
* <code>-1 = disable MapReduce workers</code>
*
* <p>
* Default is <code>0</code>
*

@ -111,6 +111,11 @@ public class ClientConnectionsEntry {
public void setFreezed(boolean freezed) {
this.freezed = freezed;
}
public void reset() {
freeConnectionsCounter.removeListeners();
freeSubscribeConnectionsCounter.removeListeners();
}
public int getFreeAmount() {
return freeConnectionsCounter.getCounter();

@ -703,24 +703,20 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
if (entry == null) {
entry = getEntry(source);
}
if (entry == null) {
RedisNodeNotFoundException ex = new RedisNodeNotFoundException("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
return RedissonPromise.newFailedFuture(ex);
}
return entry.connectionWriteOp(command);
}
private MasterSlaveEntry getEntry(NodeSource source) {
// workaround for slots in migration state
// slots handling during migration state
if (source.getRedirect() != null) {
MasterSlaveEntry e = getEntry(source.getAddr());
if (e == null) {
throw new RedisNodeNotFoundException("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
}
return e;
return getEntry(source.getAddr());
}
MasterSlaveEntry e = getEntry(source.getSlot());
if (e == null) {
throw new RedisNodeNotFoundException("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
}
return e;
return getEntry(source.getSlot());
}
@Override
@ -739,17 +735,39 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
}
}
}
if (entry == null) {
RedisNodeNotFoundException ex = new RedisNodeNotFoundException("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
return RedissonPromise.newFailedFuture(ex);
}
return entry.connectionReadOp(command, source.getAddr());
}
if (entry == null) {
RedisNodeNotFoundException ex = new RedisNodeNotFoundException("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
return RedissonPromise.newFailedFuture(ex);
}
return entry.connectionReadOp(command);
}
RFuture<RedisPubSubConnection> nextPubSubConnection(int slot) {
return getEntry(slot).nextPubSubConnection();
MasterSlaveEntry entry = getEntry(slot);
if (entry == null) {
RedisNodeNotFoundException ex = new RedisNodeNotFoundException("Node for slot: " + slot + " hasn't been discovered yet");
return RedissonPromise.newFailedFuture(ex);
}
return entry.nextPubSubConnection();
}
protected void releaseSubscribeConnection(int slot, PubSubConnectionEntry entry) {
this.getEntry(slot).returnPubSubConnection(entry);
protected void releaseSubscribeConnection(int slot, PubSubConnectionEntry pubSubEntry) {
MasterSlaveEntry entry = getEntry(slot);
if (entry == null) {
log.error("Node for slot: " + slot + " hasn't been discovered yet");
} else {
entry.returnPubSubConnection(pubSubEntry);
}
}
@Override
@ -758,7 +776,11 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
if (entry == null) {
entry = getEntry(source);
}
entry.releaseWrite(connection);
if (entry == null) {
log.error("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
} else {
entry.releaseWrite(connection);
}
}
@Override
@ -767,7 +789,12 @@ public class MasterSlaveConnectionManager implements ConnectionManager {
if (entry == null) {
entry = getEntry(source);
}
entry.releaseRead(connection);
if (entry == null) {
log.error("Node: " + source.getAddr() + " for slot: " + source.getSlot() + " hasn't been discovered yet");
} else {
entry.releaseRead(connection);
}
}
@Override

@ -143,6 +143,8 @@ public class MasterSlaveEntry {
}
}
entry.reset();
// close all connections
while (true) {
final RedisConnection connection = entry.pollConnection();

@ -198,8 +198,8 @@ abstract class ConnectionPool<T extends RedisConnection> {
}
public RFuture<T> get(RedisCommand<?> command, ClientConnectionsEntry entry) {
if (((entry.getNodeType() == NodeType.MASTER && entry.getFreezeReason() == FreezeReason.SYSTEM) || !entry.isFreezed())
&& tryAcquireConnection(entry)) {
if ((!entry.isFreezed() || entry.getFreezeReason() == FreezeReason.SYSTEM) &&
tryAcquireConnection(entry)) {
return acquireConnection(command, entry);
}

@ -33,11 +33,11 @@ import io.netty.util.concurrent.FutureListener;
abstract class EvictionTask implements Runnable {
final Deque<Integer> sizeHistory = new LinkedList<Integer>();
final int minDelay = 1;
final int minDelay = 5;
final int maxDelay = 30*60;
final int keysLimit = 300;
final int keysLimit = 100;
int delay = 10;
int delay = 5;
final CommandAsyncExecutor executor;

@ -34,6 +34,7 @@ public class MapCacheEvictionTask extends EvictionTask {
private final String maxIdleSetName;
private final String expiredChannelName;
private final String lastAccessTimeSetName;
private final String executeTaskOnceLatchName;
public MapCacheEvictionTask(String name, String timeoutSetName, String maxIdleSetName,
String expiredChannelName, String lastAccessTimeSetName, CommandAsyncExecutor executor) {
@ -43,18 +44,33 @@ public class MapCacheEvictionTask extends EvictionTask {
this.maxIdleSetName = maxIdleSetName;
this.expiredChannelName = expiredChannelName;
this.lastAccessTimeSetName = lastAccessTimeSetName;
this.executeTaskOnceLatchName = prefixName("redisson__execute_task_once_latch", name);
}
protected String prefixName(String prefix, String name) {
if (name.contains("{")) {
return prefix + ":" + name;
}
return prefix + ":{" + name + "}";
}
@Override
RFuture<Integer> execute() {
return executor.evalWriteAsync(name, LongCodec.INSTANCE, RedisCommands.EVAL_INTEGER,
"local expiredKeys1 = redis.call('zrangebyscore', KEYS[2], 0, ARGV[1], 'limit', 0, ARGV[2]); "
"if redis.call('setnx', KEYS[6], ARGV[4]) == 0 then "
+ "return 0;"
+ "end;"
+ "redis.call('expire', KEYS[6], ARGV[3]); "
+"local expiredKeys1 = redis.call('zrangebyscore', KEYS[2], 0, ARGV[1], 'limit', 0, ARGV[2]); "
+ "for i, key in ipairs(expiredKeys1) do "
+ "local v = redis.call('hget', KEYS[1], key); "
+ "if v ~= false then "
+ "local t, val = struct.unpack('dLc0', v); "
+ "local msg = struct.pack('Lc0Lc0', string.len(key), key, string.len(val), val); "
+ "redis.call('publish', KEYS[4], msg); "
+ "local listeners = redis.call('publish', KEYS[4], msg); "
+ "if (listeners == 0) then "
+ "break;"
+ "end; "
+ "end;"
+ "end;"
+ "if #expiredKeys1 > 0 then "
@ -69,7 +85,10 @@ public class MapCacheEvictionTask extends EvictionTask {
+ "if v ~= false then "
+ "local t, val = struct.unpack('dLc0', v); "
+ "local msg = struct.pack('Lc0Lc0', string.len(key), key, string.len(val), val); "
+ "redis.call('publish', KEYS[4], msg); "
+ "local listeners = redis.call('publish', KEYS[4], msg); "
+ "if (listeners == 0) then "
+ "break;"
+ "end; "
+ "end;"
+ "end;"
+ "if #expiredKeys2 > 0 then "
@ -79,8 +98,8 @@ public class MapCacheEvictionTask extends EvictionTask {
+ "redis.call('hdel', KEYS[1], unpack(expiredKeys2)); "
+ "end; "
+ "return #expiredKeys1 + #expiredKeys2;",
Arrays.<Object>asList(name, timeoutSetName, maxIdleSetName, expiredChannelName, lastAccessTimeSetName),
System.currentTimeMillis(), keysLimit);
Arrays.<Object>asList(name, timeoutSetName, maxIdleSetName, expiredChannelName, lastAccessTimeSetName, executeTaskOnceLatchName),
System.currentTimeMillis(), keysLimit, delay, 1);
}
}

@ -30,6 +30,7 @@ import org.redisson.api.annotation.REntity.TransformationMode;
import org.redisson.api.annotation.RId;
import org.redisson.client.codec.Codec;
import org.redisson.codec.CodecProvider;
import org.redisson.liveobject.misc.ClassUtils;
import org.redisson.liveobject.misc.Introspectior;
import org.redisson.liveobject.resolver.NamingScheme;
import org.redisson.misc.RedissonObjectFactory;
@ -73,7 +74,7 @@ public class AccessorInterceptor {
}
String fieldName = getFieldName(method);
Class<?> fieldType = me.getClass().getSuperclass().getDeclaredField(fieldName).getType();
Class<?> fieldType = ClassUtils.getDeclaredField(me.getClass().getSuperclass(), fieldName).getType();
if (isGetter(method, fieldName)) {
Object result = liveMap.get(fieldName);
@ -92,7 +93,7 @@ public class AccessorInterceptor {
}
if (isSetter(method, fieldName)) {
Object arg = args[0];
if (arg != null && arg.getClass().isAnnotationPresent(REntity.class)) {
if (arg != null && ClassUtils.isAnnotationPresent(arg.getClass(), REntity.class)) {
throw new IllegalStateException("REntity object should be attached to Redisson first");
}
@ -100,7 +101,7 @@ public class AccessorInterceptor {
RLiveObject liveObject = (RLiveObject) arg;
Class<? extends Object> rEntity = liveObject.getClass().getSuperclass();
REntity anno = rEntity.getAnnotation(REntity.class);
REntity anno = ClassUtils.getAnnotation(rEntity, REntity.class);
NamingScheme ns = anno.namingScheme()
.getDeclaredConstructor(Codec.class)
.newInstance(codecProvider.getCodec(anno, (Class) rEntity));
@ -113,8 +114,8 @@ public class AccessorInterceptor {
if (!(arg instanceof RObject)
&& (arg instanceof Collection || arg instanceof Map)
&& TransformationMode.ANNOTATION_BASED
.equals(me.getClass().getSuperclass()
.getAnnotation(REntity.class).fieldTransformation())) {
.equals(ClassUtils.getAnnotation(me.getClass().getSuperclass(),
REntity.class).fieldTransformation())) {
RObject rObject = objectBuilder.createObject(((RLiveObject) me).getLiveObjectId(), me.getClass().getSuperclass(), arg.getClass(), fieldName);
if (arg != null) {
if (rObject instanceof Collection) {
@ -147,7 +148,9 @@ public class AccessorInterceptor {
}
private String getFieldName(Method method) {
return method.getName().substring(3, 4).toLowerCase() + method.getName().substring(4);
String name = method.getName();
int i = name.startsWith("is") ? 3 : 4;
return name.substring(i - 1, i).toLowerCase() + name.substring(i);
}
private boolean isGetter(Method method, String fieldName) {

@ -30,6 +30,7 @@ import org.redisson.api.RMap;
import org.redisson.api.RedissonClient;
import org.redisson.api.annotation.REntity;
import org.redisson.codec.CodecProvider;
import org.redisson.liveobject.misc.ClassUtils;
import org.redisson.liveobject.resolver.NamingScheme;
/**
@ -61,11 +62,11 @@ public class LiveObjectInterceptor {
this.codecProvider = codecProvider;
this.originalClass = entityClass;
this.idFieldName = idFieldName;
REntity anno = (REntity) entityClass.getAnnotation(REntity.class);
REntity anno = (REntity) ClassUtils.getAnnotation(entityClass, REntity.class);
this.codecClass = anno.codec();
try {
this.namingScheme = anno.namingScheme().getDeclaredConstructor(Codec.class).newInstance(codecProvider.getCodec(anno, originalClass));
this.idFieldType = originalClass.getDeclaredField(idFieldName).getType();
this.idFieldType = ClassUtils.getDeclaredField(originalClass, idFieldName).getType();
} catch (Exception e) {
throw new IllegalArgumentException(e);
}

@ -44,6 +44,7 @@ import org.redisson.api.annotation.REntity;
import org.redisson.api.annotation.RObjectField;
import org.redisson.client.codec.Codec;
import org.redisson.codec.CodecProvider;
import org.redisson.liveobject.misc.ClassUtils;
import org.redisson.liveobject.resolver.NamingScheme;
import org.redisson.misc.RedissonObjectFactory;
@ -116,12 +117,12 @@ public class RedissonObjectBuilder {
* WARNING: rEntity has to be the class of @This object.
*/
private Codec getFieldCodec(Class<?> rEntity, Class<? extends RObject> rObjectClass, String fieldName) throws Exception {
Field field = rEntity.getDeclaredField(fieldName);
Field field = ClassUtils.getDeclaredField(rEntity, fieldName);
if (field.isAnnotationPresent(RObjectField.class)) {
RObjectField anno = field.getAnnotation(RObjectField.class);
return codecProvider.getCodec(anno, rEntity, rObjectClass, fieldName);
} else {
REntity anno = rEntity.getAnnotation(REntity.class);
REntity anno = ClassUtils.getAnnotation(rEntity, REntity.class);
return codecProvider.getCodec(anno, (Class<?>) rEntity);
}
}
@ -131,7 +132,7 @@ public class RedissonObjectBuilder {
*/
private NamingScheme getFieldNamingScheme(Class<?> rEntity, String fieldName, Codec c) throws Exception {
if (!namingSchemeCache.containsKey(fieldName)) {
REntity anno = rEntity.getAnnotation(REntity.class);
REntity anno = ClassUtils.getAnnotation(rEntity, REntity.class);
namingSchemeCache.putIfAbsent(fieldName, anno.namingScheme()
.getDeclaredConstructor(Codec.class)
.newInstance(c));

@ -45,9 +45,15 @@
package org.redisson.liveobject.misc;
import org.redisson.api.RObject;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.List;
/**
*
@ -57,7 +63,7 @@ public class ClassUtils {
public static void setField(Object obj, String fieldName, Object value) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
Field field = getDeclaredField(obj.getClass(), fieldName);
if (!field.isAccessible()) {
field.setAccessible(true);
}
@ -69,7 +75,7 @@ public class ClassUtils {
public static <T extends Annotation> T getAnnotation(Class<?> clazz, String fieldName, Class<T> annotationClass) {
try {
Field field = clazz.getDeclaredField(fieldName);
Field field = getDeclaredField(clazz, fieldName);
if (!field.isAccessible()) {
field.setAccessible(true);
}
@ -78,10 +84,19 @@ public class ClassUtils {
return null;
}
}
public static <T extends Annotation> T getAnnotation(Class<?> clazz, Class<T> annotationClass) {
for (Class<?> c : getClassHierarchy(clazz)) {
if (c.getAnnotation(annotationClass) != null) {
return c.getAnnotation(annotationClass);
}
}
return null;
}
public static <T> T getField(Object obj, String fieldName) {
try {
Field field = obj.getClass().getDeclaredField(fieldName);
Field field = getDeclaredField(obj.getClass(), fieldName);
if (!field.isAccessible()) {
field.setAccessible(true);
}
@ -90,6 +105,38 @@ public class ClassUtils {
throw new IllegalArgumentException(e);
}
}
public static Field getDeclaredField(Class<?> clazz, String fieldName) throws NoSuchFieldException {
for (Class c : getClassHierarchy(clazz)) {
for (Field field : c.getDeclaredFields()) {
if (field.getName().equals(fieldName)) {
return field;
}
}
}
throw new NoSuchFieldException("No such field: " + fieldName);
}
public static boolean isAnnotationPresent(Class<?> clazz, Class<? extends Annotation> annotation) {
for (Class<?> c : getClassHierarchy(clazz)) {
if (c.isAnnotationPresent(annotation)) {
return true;
}
}
return false;
}
private static Iterable<Class<?>> getClassHierarchy(Class<?> clazz) {
// Don't descend into hierarchy for RObjects
if (Arrays.asList(clazz.getInterfaces()).contains(RObject.class)) {
return Collections.<Class<?>>singleton(clazz);
}
List<Class<?>> classes = new ArrayList<Class<?>>();
for (Class c = clazz; c != null; c = c.getSuperclass()) {
classes.add(c);
}
return classes;
}
/**
* Searches through all methods looking for one with the specified name that

@ -16,6 +16,11 @@
package org.redisson.liveobject.misc;
import java.lang.annotation.Annotation;
import java.lang.reflect.Field;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import net.bytebuddy.description.field.FieldDescription;
import net.bytebuddy.description.field.FieldList;
import net.bytebuddy.description.method.MethodDescription;
@ -59,8 +64,15 @@ public class Introspectior {
}
public static FieldList<FieldDescription.InDefinedShape> getFieldsWithAnnotation(Class<?> c, Class<? extends Annotation> a) {
return getTypeDescription(c)
.getDeclaredFields()
return getAllFields(c)
.filter(ElementMatchers.isAnnotatedWith(a));
}
public static FieldList<FieldDescription.InDefinedShape> getAllFields(Class<?> cls) {
List<Field> fields = new ArrayList<Field>();
for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
Collections.addAll(fields, c.getDeclaredFields());
}
return new FieldList.ForLoadedFields(fields);
}
}

@ -19,9 +19,11 @@ import java.io.Serializable;
import java.util.UUID;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.redisson.Redisson;
import org.redisson.api.RExecutorService;
import org.redisson.api.RFuture;
import org.redisson.api.RScheduledExecutorService;
@ -144,7 +146,8 @@ public class CoordinatorTask<KOut, VOut> implements Callable<Object>, Serializab
}
if (timeout > 0) {
java.util.concurrent.Future<?> collatorFuture = redisson.getConfig().getExecutor().submit(collatorTask);
ExecutorService executor = ((Redisson) redisson).getConnectionManager().getExecutor();
java.util.concurrent.Future<?> collatorFuture = executor.submit(collatorTask);
try {
return collatorFuture.get(timeout - timeSpent, TimeUnit.MILLISECONDS);
} catch (InterruptedException e) {

@ -34,6 +34,7 @@ import org.redisson.api.annotation.RId;
import org.redisson.client.codec.Codec;
import org.redisson.codec.CodecProvider;
import org.redisson.config.Config;
import org.redisson.liveobject.misc.ClassUtils;
import org.redisson.liveobject.misc.Introspectior;
import org.redisson.liveobject.resolver.NamingScheme;
@ -104,9 +105,9 @@ public class RedissonObjectFactory {
Class<? extends Object> type = rr.getType();
CodecProvider codecProvider = redisson.getConfig().getCodecProvider();
if (type != null) {
if (type.isAnnotationPresent(REntity.class)) {
if (ClassUtils.isAnnotationPresent(type, REntity.class)) {
RLiveObjectService liveObjectService = redisson.getLiveObjectService();
REntity anno = type.getAnnotation(REntity.class);
REntity anno = ClassUtils.getAnnotation(type, REntity.class);
NamingScheme ns = anno.namingScheme()
.getDeclaredConstructor(Codec.class)
.newInstance(codecProvider.getCodec(anno, type));
@ -151,7 +152,7 @@ public class RedissonObjectFactory {
}
public static RedissonReference toReference(Config config, Object object) {
if (object != null && object.getClass().isAnnotationPresent(REntity.class)) {
if (object != null && ClassUtils.isAnnotationPresent(object.getClass(), REntity.class)) {
throw new IllegalArgumentException("REntity should be attached to Redisson before save");
}
@ -169,14 +170,14 @@ public class RedissonObjectFactory {
try {
if (object instanceof RLiveObject) {
Class<? extends Object> rEntity = object.getClass().getSuperclass();
REntity anno = rEntity.getAnnotation(REntity.class);
REntity anno = ClassUtils.getAnnotation(rEntity, REntity.class);
NamingScheme ns = anno.namingScheme()
.getDeclaredConstructor(Codec.class)
.newInstance(config.getCodecProvider().getCodec(anno, (Class) rEntity));
String name = Introspectior
.getFieldsWithAnnotation(rEntity, RId.class)
.getOnly().getName();
Class<?> type = rEntity.getDeclaredField(name).getType();
Class<?> type = ClassUtils.getDeclaredField(rEntity, name).getType();
return new RedissonReference(rEntity,
ns.getName(rEntity, type, name, ((RLiveObject) object).getLiveObjectId()));
}

@ -17,8 +17,6 @@ package org.redisson.pubsub;
import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.LinkedList;
import java.util.Queue;
import java.util.Set;
import java.util.concurrent.CountDownLatch;
@ -58,6 +56,12 @@ public class AsyncSemaphore {
}
}
public void removeListeners() {
synchronized (this) {
listeners.clear();
}
}
public void acquire(Runnable listener) {
boolean run = false;

@ -33,6 +33,8 @@ public class CacheConfig {
private long ttl;
private long maxIdleTime;
private int maxSize;
/**
* Creates config object with
@ -72,6 +74,21 @@ public class CacheConfig {
this.ttl = ttl;
}
public int getMaxSize() {
return maxSize;
}
/**
* Set max size of map. Superfluous elements are evicted using LRU algorithm.
*
* @param maxSize - max size
* If <code>0</code> the cache is unbounded (default).
*/
public void setMaxSize(int maxSize) {
this.maxSize = maxSize;
}
public long getMaxIdleTime() {
return maxIdleTime;
}

@ -212,11 +212,9 @@ public class RedissonSpringCacheManager implements CacheManager, ResourceLoaderA
if (config == null) {
config = createDefaultConfig();
configMap.put(name, config);
return createMap(name, config);
}
if (config.getMaxIdleTime() == 0 && config.getTTL() == 0) {
if (config.getMaxIdleTime() == 0 && config.getTTL() == 0 && config.getMaxSize() == 0) {
return createMap(name, config);
}
@ -248,6 +246,8 @@ public class RedissonSpringCacheManager implements CacheManager, ResourceLoaderA
Cache oldCache = instanceMap.putIfAbsent(name, cache);
if (oldCache != null) {
cache = oldCache;
} else {
map.setMaxSize(config.getMaxSize());
}
return cache;
}

@ -248,6 +248,10 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
publishEvent(new SessionCreatedEvent(this, session));
}
} else if (deletedTopic.getPatternNames().contains(pattern)) {
if (!body.contains(":")) {
return;
}
String id = body.split(":")[1];
RedissonSession session = new RedissonSession(id);
if (session.load()) {
@ -257,6 +261,10 @@ public class RedissonSessionRepository implements FindByIndexNameSessionReposito
publishEvent(new SessionDeletedEvent(this, id));
}
} else if (expiredTopic.getPatternNames().contains(pattern)) {
if (!body.contains(":")) {
return;
}
String id = body.split(":")[1];
RedissonSession session = new RedissonSession(id);
if (session.load()) {

@ -1,5 +1,7 @@
package org.redisson;
import static org.assertj.core.api.Assertions.assertThat;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -9,13 +11,13 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
import static org.assertj.core.api.Assertions.*;
import org.junit.Assert;
import org.junit.Assume;
import org.junit.Test;
import org.redisson.api.RBatch;
import org.redisson.api.RFuture;
import org.redisson.api.RListAsync;
import org.redisson.api.RMapCacheAsync;
import org.redisson.api.RScript;
import org.redisson.api.RScript.Mode;
import org.redisson.client.RedisException;
@ -41,6 +43,16 @@ public class RedissonBatchTest extends BaseTest {
System.out.println(t);
}
@Test
public void testWriteTimeout() {
RBatch batch = redisson.createBatch();
for (int i = 0; i < 200000; i++) {
RMapCacheAsync<String, String> map = batch.getMapCache("test");
map.putAsync("" + i, "" + i, 10, TimeUnit.SECONDS);
}
batch.execute();
}
@Test
public void testSkipResult() {
Assume.assumeTrue(RedisRunner.getDefaultRedisServerInstance().getRedisVersion().compareTo("3.2.0") > 0);

@ -1129,11 +1129,9 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
SimpleObject s = new SimpleObject();
s = service.persist(s);
so.setSo(s);
assertThat(s.getId()).isNotNull();
so.getObjects().add(s);
so = redisson.getLiveObjectService().detach(so);
assertThat(so.getSo().getId()).isEqualTo(s.getId());
assertThat(so.getObjects().get(0).getId()).isEqualTo(so.getSo().getId());
@ -1462,5 +1460,181 @@ public class RedissonLiveObjectServiceTest extends BaseTest {
sg = redisson.getLiveObjectService().persist(sg);
assertThat(sg.getName()).isEqualTo("1234");
}
@REntity
public static class Animal {
@RId(generator = LongGenerator.class)
private Long id;
private String name;
protected Animal() {
}
public Animal(String name) {
super();
this.name = name;
}
public String getName() {
return name;
}
}
public static class Dog extends Animal {
private String breed;
public Dog(String name) {
super(name);
}
protected Dog() {
}
public void setBreed(String breed) {
this.breed = breed;
}
public String getBreed() {
return breed;
}
}
@Test
public void testInheritedREntity() {
Dog d = new Dog("Fido");
d.setBreed("lab");
d = redisson.getLiveObjectService().persist(d);
assertThat(d.getName()).isEqualTo("Fido");
assertThat(d.getBreed()).isEqualTo("lab");
}
@Test
public void testMapOfInheritedEntity() {
RMap<String, Dog> dogs = redisson.getMap("dogs");
Dog d = new Dog("Fido");
d = redisson.getLiveObjectService().persist(d);
d.setBreed("lab");
dogs.put("key", d);
dogs = redisson.getMap("dogs");
assertThat(dogs.size()).isEqualTo(1);
assertThat(dogs.get("key").getBreed()).isEqualTo("lab");
}
public static class MyCustomer extends Customer {
@RCascade(RCascadeType.ALL)
private List<Order> specialOrders = new ArrayList<>();
public MyCustomer() {
}
public MyCustomer(String id) {
super(id);
}
public void addSpecialOrder(Order order) {
getSpecialOrders().add(order);
}
public void setSpecialOrders(List<Order> orders) {
this.specialOrders = orders;
}
public List<Order> getSpecialOrders() {
return specialOrders;
}
}
@Test
public void testCyclicRefsWithInheritedREntity() {
MyCustomer customer = new MyCustomer("12");
customer = redisson.getLiveObjectService().persist(customer);
Order order = new Order();
order = redisson.getLiveObjectService().persist(order);
order.setCustomer(customer);
customer.getOrders().add(order);
Order special = new Order();
special = redisson.getLiveObjectService().persist(special);
order.setCustomer(customer);
customer.addSpecialOrder(special);
customer = redisson.getLiveObjectService().detach(customer);
assertThat(customer.getClass()).isSameAs(MyCustomer.class);
assertThat(customer.getId()).isNotNull();
List<Order> orders = customer.getOrders();
assertThat(orders.get(0)).isNotNull();
List<Order> specials = customer.getSpecialOrders();
assertThat(specials.get(0)).isNotNull();
customer = redisson.getLiveObjectService().get(MyCustomer.class, customer.getId());
assertThat(customer.getId()).isNotNull();
assertThat(customer.getOrders().get(0)).isNotNull();
assertThat(customer.getSpecialOrders().get(0)).isNotNull();
}
public static class MyObjectWithList extends ObjectWithList {
protected MyObjectWithList() {
super();
}
private String name;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
@Test
public void testStoreInnerObjectWithInheritedREntity() {
RLiveObjectService service = redisson.getLiveObjectService();
MyObjectWithList so = new MyObjectWithList();
so = service.persist(so);
SimpleObject s = new SimpleObject();
s = service.persist(s);
so.setSo(s);
assertThat(s.getId()).isNotNull();
so.getObjects().add(s);
so.setName("name");
so = redisson.getLiveObjectService().detach(so);
assertThat(so.getSo().getId()).isEqualTo(s.getId());
assertThat(so.getObjects().get(0).getId()).isEqualTo(so.getSo().getId());
assertThat(so.getName()).isEqualTo("name");
}
@REntity
public static class HasIsAccessor {
@RId(generator = LongGenerator.class)
private Long id;
boolean good;
public boolean isGood() {
return good;
}
public void setGood(boolean good) {
this.good = good;
}
}
@Test
public void testIsAccessor() {
HasIsAccessor o = new HasIsAccessor();
o.setGood(true);
o = redisson.getLiveObjectService().persist(o);
assertThat(o.isGood()).isEqualTo(true);
}
}

@ -242,6 +242,21 @@ public class RedissonMapReduceTest extends BaseTest {
}
@Test
public void testCollatorTimeout() {
RMap<String, String> map = getMap();
map.put("1", "Alice was beginning to get very tired");
RMapReduce<String, String, String, Integer> mapReduce = map.<String, Integer>mapReduce()
.mapper(new WordMapperInject())
.reducer(new WordReducerInject())
.timeout(10, TimeUnit.SECONDS);
Integer res = mapReduce.execute(new WordCollatorInject());
assertThat(res).isEqualTo(7);
}
@Test
public void testInjector() {
RMap<String, String> map = getMap();

@ -27,6 +27,8 @@ import org.redisson.client.codec.StringCodec;
import org.redisson.codec.JsonJacksonCodec;
import org.redisson.config.Config;
import net.bytebuddy.utility.RandomString;
public class RedissonMapTest extends BaseMapTest {
public static class SimpleKey implements Serializable {
@ -421,6 +423,16 @@ public class RedissonMapTest extends BaseMapTest {
assertThat(rmap.readAllEntrySet()).containsExactlyElementsOf(map.entrySet());
}
@Test
public void testWriteTimeout() {
Map<String, String> map = redisson.getMap("simple");
Map<String, String> joinMap = new HashMap<>();
for (int i = 0; i < 200000; i++) {
joinMap.put(RandomString.make(1024), RandomString.make(1024));
}
map.putAll(joinMap);
}
@Test
public void testPutAll() {
Map<Integer, String> map = redisson.getMap("simple");

@ -5,16 +5,27 @@ import java.util.List;
import java.util.concurrent.TimeUnit;
import static org.junit.Assert.*;
import org.junit.Test;
import org.redisson.api.LocalCachedMapOptions;
import org.redisson.api.RBatch;
import org.redisson.api.RBatchReactive;
import org.redisson.api.RBucket;
import org.redisson.api.RBucketAsync;
import org.redisson.api.RBucketReactive;
import org.redisson.api.RDelayedQueue;
import org.redisson.api.RGeo;
import org.redisson.api.RList;
import org.redisson.api.RListMultimap;
import org.redisson.api.RLiveObject;
import org.redisson.api.RLiveObjectService;
import org.redisson.api.RLocalCachedMap;
import org.redisson.api.RMap;
import org.redisson.api.RMapCache;
import org.redisson.api.RPriorityQueue;
import org.redisson.api.RQueue;
import org.redisson.api.RScoredSortedSet;
import org.redisson.api.RSet;
import org.redisson.api.RSetCache;
import org.redisson.api.RSetMultimap;
import org.redisson.client.protocol.ScoredEntry;
/**
@ -22,7 +33,7 @@ import org.redisson.client.protocol.ScoredEntry;
* @author Rui Gu (https://github.com/jackygurui)
*/
public class RedissonReferenceTest extends BaseTest {
@Test
public void testBasic() {
RBucket<Object> b1 = redisson.getBucket("b1");
@ -36,10 +47,10 @@ public class RedissonReferenceTest extends BaseTest {
b4.set(redisson.getMapCache("testCache"));
assertTrue(b4.get() instanceof RedissonMapCache);
((RedissonMapCache) b4.get()).fastPut(b1, b2, 1, TimeUnit.MINUTES);
assertEquals("b2", ((RBucket)((RedissonMapCache) b4.get()).get(b1)).getName());
assertEquals("b2", ((RBucket) ((RedissonMapCache) b4.get()).get(b1)).getName());
RBucket<Object> b5 = redisson.getBucket("b5");
RLiveObjectService service = redisson.getLiveObjectService();
RedissonLiveObjectServiceTest.TestREntity rlo = new RedissonLiveObjectServiceTest.TestREntity("123");
rlo = service.persist(rlo);
rlo.setName("t1");
@ -48,9 +59,9 @@ public class RedissonReferenceTest extends BaseTest {
assertTrue(redisson.getBucket("b5").get() instanceof RLiveObject);
assertEquals("t1", ((RedissonLiveObjectServiceTest.TestREntity) redisson.getBucket("b5").get()).getName());
assertEquals("t2", ((RedissonLiveObjectServiceTest.TestREntity) redisson.getBucket("b5").get()).getValue());
}
@Test
public void testBatch() {
RBatch batch = redisson.createBatch();
@ -61,17 +72,17 @@ public class RedissonReferenceTest extends BaseTest {
b1.setAsync(b2);
b3.setAsync(b1);
batch.execute();
batch = redisson.createBatch();
batch.getBucket("b1").getAsync();
batch.getBucket("b2").getAsync();
batch.getBucket("b3").getAsync();
List<RBucket> result = (List<RBucket>)batch.execute();
List<RBucket> result = (List<RBucket>) batch.execute();
assertEquals("b2", result.get(0).getName());
assertEquals("b3", result.get(1).getName());
assertEquals("b1", result.get(2).getName());
}
@Test
public void testNormalToReactive() {
RBatch batch = redisson.createBatch();
@ -82,7 +93,7 @@ public class RedissonReferenceTest extends BaseTest {
b1.setAsync(b2);
b3.setAsync(b1);
batch.execute();
RBatchReactive b = Redisson.createReactive(redisson.getConfig()).createBatch();
b.getBucket("b1").get();
b.getBucket("b2").get();
@ -92,7 +103,7 @@ public class RedissonReferenceTest extends BaseTest {
assertEquals("b3", result.get(1).getName());
assertEquals("b1", result.get(2).getName());
}
@Test
public void testWithList() {
RSet<RBucket<String>> b1 = redisson.getSet("set");
@ -103,7 +114,7 @@ public class RedissonReferenceTest extends BaseTest {
assertEquals(b2.get(), b1.iterator().next().get());
assertEquals(2, redisson.getKeys().count());
}
@Test
public void testWithZSet() {
RScoredSortedSet<RBucket<String>> b1 = redisson.getScoredSortedSet("set");
@ -115,7 +126,97 @@ public class RedissonReferenceTest extends BaseTest {
Collection<ScoredEntry<RBucket<String>>> entryRange = b1.entryRange(0, 1);
assertEquals(b2.get(), entryRange.iterator().next().getValue().get());
}
@Test
public void testReadAll() throws InterruptedException {
RSetCache<RBucket<String>> b1 = redisson.getSetCache("set");
RBucket<String> b2 = redisson.getBucket("bucket");
b1.add(b2, 1, TimeUnit.MINUTES);
b2.set("test1");
assertEquals(b2.get(), b1.readAll().iterator().next().get());
assertEquals(2, redisson.getKeys().count());
RMapCache<String, RSetCache<RBucket<String>>> b3 = redisson.getMapCache("map");
b3.put("1", b1);
assertEquals(b2.get(), b3.readAllMap().get("1").iterator().next().get());
assertEquals(b2.get(), b3.readAllEntrySet().iterator().next().getValue().iterator().next().get());
assertEquals(b2.get(), b3.readAllValues().iterator().next().iterator().next().get());
RMapCache<RBucket<String>, RSetCache<RBucket<String>>> b4 = redisson.getMapCache("map1");
b4.put(b2, b1);
assertEquals(b2.get(), b4.readAllKeySet().iterator().next().get());
RPriorityQueue<RBucket<String>> q1 = redisson.getPriorityQueue("q1");
q1.add(b2);
assertEquals(b2.get(), q1.readAll().get(0).get());
RQueue<RBucket<String>> q2 = redisson.getQueue("q2");
q2.add(b2);
assertEquals(b2.get(), q2.readAll().get(0).get());
RDelayedQueue<RBucket<String>> q3 = redisson.getDelayedQueue(q2);
q3.offer(b2, 10, TimeUnit.MINUTES);
assertEquals(b2.get(), q3.readAll().get(0).get());
RList<RBucket<String>> l1 = redisson.getList("l1");
l1.add(b2);
assertEquals(b2.get(), l1.readAll().get(0).get());
RList<RBucket<String>> sl1 = l1.subList(0, 0);
assertEquals(b2.get(), sl1.readAll().get(0).get());
RLocalCachedMap<String, RBucket<String>> m1 = redisson.getLocalCachedMap("m1", LocalCachedMapOptions.defaults());
m1.put("1", b2);
assertEquals(b2.get(), m1.readAllMap().get("1").get());
assertEquals(b2.get(), m1.readAllEntrySet().iterator().next().getValue().get());
assertEquals(b2.get(), m1.readAllValues().iterator().next().get());
m1 = redisson.getLocalCachedMap("m1", LocalCachedMapOptions.defaults());
assertEquals(b2.get(), m1.readAllMap().get("1").get());
assertEquals(b2.get(), m1.readAllEntrySet().iterator().next().getValue().get());
assertEquals(b2.get(), m1.readAllValues().iterator().next().get());
RLocalCachedMap<RBucket<String>, RBucket<String>> m2 = redisson.getLocalCachedMap("m2", LocalCachedMapOptions.defaults());
m2.put(b2, b2);
assertEquals(b2.get(), m2.readAllKeySet().iterator().next().get());
m2 = redisson.getLocalCachedMap("m2", LocalCachedMapOptions.defaults());
assertEquals(b2.get(), m2.readAllKeySet().iterator().next().get());
RMap<String, RSetCache<RBucket<String>>> m3 = redisson.getMap("m3");
m3.put("1", b1);
assertEquals(b2.get(), m3.readAllMap().get("1").iterator().next().get());
assertEquals(b2.get(), m3.readAllEntrySet().iterator().next().getValue().iterator().next().get());
assertEquals(b2.get(), m3.readAllValues().iterator().next().iterator().next().get());
RMap<RBucket<String>, RSetCache<RBucket<String>>> m4 = redisson.getMap("m4");
m4.put(b2, b1);
assertEquals(b2.get(), m4.readAllKeySet().iterator().next().get());
//multimap
RGeo<RBucket<String>> g1 = redisson.getGeo("g1");
g1.add(13.361389, 38.115556, b2);
assertEquals(b2.get(), g1.readAll().iterator().next().get());
RScoredSortedSet<RBucket<String>> s1 = redisson.getScoredSortedSet("s1");
s1.add(0.0, b2);
assertEquals(b2.get(), s1.readAll().iterator().next().get());
RListMultimap<String, RBucket<String>> mm1 = redisson.getListMultimap("mm1");
mm1.put("1", b2);
assertEquals(b2.get(), mm1.get("1").readAll().get(0).get());
RListMultimap<RBucket<String>, RBucket<String>> mm2 = redisson.getListMultimap("mm2");
mm2.put(b2, b2);
assertEquals(b2.get(), mm2.get(b2).readAll().get(0).get());
RSetMultimap<String, RBucket<String>> mm3 = redisson.getSetMultimap("mm3");
mm3.put("1", b2);
assertEquals(b2.get(), mm3.get("1").readAll().iterator().next().get());
RSetMultimap<RBucket<String>, RBucket<String>> mm4 = redisson.getSetMultimap("mm4");
mm4.put(b2, b2);
assertEquals(b2.get(), mm4.get(b2).readAll().iterator().next().get());
}
@Test
public void testWithMap() {
RMap<RBucket<RMap>, RBucket<RMap>> map = redisson.getMap("set");

Loading…
Cancel
Save