Merge branch 'master' into 3.0.0

# Conflicts:
#	pom.xml
#	redisson-all/pom.xml
#	redisson-tomcat/pom.xml
#	redisson-tomcat/redisson-tomcat-6/pom.xml
#	redisson-tomcat/redisson-tomcat-7/pom.xml
#	redisson-tomcat/redisson-tomcat-8/pom.xml
#	redisson-tomcat/redisson-tomcat-9/pom.xml
#	redisson/pom.xml
pull/1821/head
Nikita 7 years ago
commit 60816c0836

@ -4,6 +4,24 @@ Redisson Releases History
Try __[Redisson PRO](https://redisson.pro)__ version.
### 15-Feb-2018 - versions 2.11.1 and 3.6.1 released
Feature - `RedissonClusteredSpringLocalCachedCacheManager` added. Please read [documentation](https://github.com/redisson/redisson/wiki/14.-Integration-with-frameworks/#1421-spring-cache-local-cache-and-data-partitioning) for more details
Feature - `rangeTailReversed`, `rangeHeadReversed` and `rangeReversed` methods added to `RLexSortedSet` object
Feature - `RBucketsAsync` interface added
Feature - `scanInterval` setting added for Sentinel mode
Feature - `RLocalCachedMap.clearLocalCache` method added
Fixed - remove `hset` command invocation during `RMapCache` entry loading
Fixed - buffer leak in `replace` and `remove` methods of `RLocalCachedMap` object
Fixed - `RRemoteService` object throws NPE
Fixed - Multimap cluster compatibility
Fixed - Enum support for Live Objects
Fixed - Jackson 2.9 compatibility
Fixed - `RTopic.removeAllListeners` got blocked on invocation
Fixed - possible pubsub listeners leak
Fixed - `RBatch` throws NPE with big pipeline in atomic mode
Fixed - Warning about `CommandDecoder.decode()` method
### 29-Jan-2018 - versions 2.11.0 and 3.6.0 released
Feature - __`atomic` setting added to RBatch object__ Please read [documentation](https://github.com/redisson/redisson/wiki/10.-additional-features#103-execution-batches-of-commands) for more details

@ -6,8 +6,8 @@ Based on high-performance async and lock-free Java Redis client and [Netty](http
| Stable <br/> Release Version | Release Date | JDK Version<br/> compatibility | `CompletionStage` <br/> support | `ProjectReactor` version<br/> compatibility |
| ------------- | ------------- | ------------| -----------| -----------|
| 3.6.0 | 29.01.2018 | 1.8+ | Yes | 3.1.x |
| 2.11.0 | 29.01.2018 | 1.6, 1.7, 1.8 and Android | No | 2.0.8 |
| 3.6.1 | 15.02.2018 | 1.8, 1.9+ | Yes | 3.1.x |
| 2.11.1 | 15.02.2018 | 1.6, 1.7, 1.8, 1.9 and Android | No | 2.0.8 |
Features
@ -88,23 +88,23 @@ Quick start
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>3.6.0</version>
<version>3.6.1</version>
</dependency>
<!-- JDK 1.6+ compatible -->
<dependency>
<groupId>org.redisson</groupId>
<artifactId>redisson</artifactId>
<version>2.11.0</version>
<version>2.11.1</version>
</dependency>
#### Gradle
// JDK 1.8+ compatible
compile 'org.redisson:redisson:3.6.0'
compile 'org.redisson:redisson:3.6.1'
// JDK 1.6+ compatible
compile 'org.redisson:redisson:2.11.0'
compile 'org.redisson:redisson:2.11.1'
#### Java
@ -129,11 +129,11 @@ RExecutorService executor = redisson.getExecutorService("myExecutorService");
Downloads
===============================
[Redisson 3.6.0](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.6.0&e=jar),
[Redisson node 3.6.0](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.6.0&e=jar)
[Redisson 3.6.1](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=3.6.1&e=jar),
[Redisson node 3.6.1](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=3.6.1&e=jar)
[Redisson 2.11.0](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.11.0&e=jar),
[Redisson node 2.11.0](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.11.0&e=jar)
[Redisson 2.11.1](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson&v=2.11.1&e=jar),
[Redisson node 2.11.1](https://repository.sonatype.org/service/local/artifact/maven/redirect?r=central-proxy&g=org.redisson&a=redisson-all&v=2.11.1&e=jar)
### Supported by

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

@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.catalina.session.StandardSession;
import org.redisson.api.RMap;
import org.redisson.tomcat.RedissonSessionManager.ReadMode;
import org.redisson.tomcat.RedissonSessionManager.UpdateMode;
/**
* Redisson Session object for Apache Tomcat
@ -37,11 +38,13 @@ public class RedissonSession extends StandardSession {
private final Map<String, Object> attrs;
private RMap<String, Object> map;
private final RedissonSessionManager.ReadMode readMode;
private final UpdateMode updateMode;
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode) {
public RedissonSession(RedissonSessionManager manager, ReadMode readMode, UpdateMode updateMode) {
super(manager);
this.redissonManager = manager;
this.readMode = readMode;
this.updateMode = updateMode;
try {
Field attr = StandardSession.class.getDeclaredField("attributes");
@ -144,7 +147,7 @@ public class RedissonSession extends StandardSession {
public void setAttribute(String name, Object value, boolean notify) {
super.setAttribute(name, value, notify);
if (map != null && value != null) {
if (updateMode == UpdateMode.DEFAULT && map != null && value != null) {
map.fastPut(name, value);
}
}
@ -153,7 +156,7 @@ public class RedissonSession extends StandardSession {
protected void removeAttributeInternal(String name, boolean notify) {
super.removeAttributeInternal(name, notify);
if (map != null) {
if (updateMode == UpdateMode.DEFAULT && map != null) {
map.fastRemove(name);
}
}

@ -17,7 +17,6 @@ package org.redisson.tomcat;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpSession;
@ -159,7 +158,7 @@ public class RedissonSessionManager extends ManagerBase implements Lifecycle {
@Override
public Session createEmptySession() {
return new RedissonSession(this, readMode);
return new RedissonSession(this, readMode, updateMode);
}
@Override
@ -218,18 +217,14 @@ public class RedissonSessionManager extends ManagerBase implements Lifecycle {
lifecycle.fireLifecycleEvent(STOP_EVENT, null);
}
public void store(HttpSession session) {
public void store(HttpSession session) throws IOException {
if (session == null) {
return;
}
if (updateMode == UpdateMode.AFTER_REQUEST) {
Enumeration<String> names = session.getAttributeNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Object value = session.getAttribute(name);
session.setAttribute(name, value);
}
RedissonSession sess = (RedissonSession) findSession(session.getId());
sess.save();
}
}

@ -1,5 +1,7 @@
package org.redisson.tomcat;
import java.nio.file.Paths;
import org.apache.catalina.Engine;
import org.apache.catalina.Host;
import org.apache.catalina.LifecycleException;
@ -56,7 +58,8 @@ public class TomcatServer {
localHost.setAutoDeploy(false);
StandardContext rootContext = (StandardContext) server.createContext(contextPath, "webapp");
rootContext.setDefaultWebXml("web.xml");
String s = Paths.get("").toAbsolutePath().resolve("src/test/webapp/META-INF/context.xml").toString();
rootContext.setDefaultContextXml(s);
localHost.addChild(rootContext);
Engine engine = server.createEngine();

@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.catalina.session.StandardSession;
import org.redisson.api.RMap;
import org.redisson.tomcat.RedissonSessionManager.ReadMode;
import org.redisson.tomcat.RedissonSessionManager.UpdateMode;
/**
* Redisson Session object for Apache Tomcat
@ -37,11 +38,14 @@ public class RedissonSession extends StandardSession {
private final Map<String, Object> attrs;
private RMap<String, Object> map;
private final RedissonSessionManager.ReadMode readMode;
private final UpdateMode updateMode;
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode) {
public RedissonSession(RedissonSessionManager manager, ReadMode readMode, UpdateMode updateMode) {
super(manager);
this.redissonManager = manager;
this.readMode = readMode;
this.updateMode = updateMode;
try {
Field attr = StandardSession.class.getDeclaredField("attributes");
attrs = (Map<String, Object>) attr.get(this);
@ -148,7 +152,7 @@ public class RedissonSession extends StandardSession {
public void setAttribute(String name, Object value, boolean notify) {
super.setAttribute(name, value, notify);
if (map != null && value != null) {
if (updateMode == UpdateMode.DEFAULT && map != null && value != null) {
map.fastPut(name, value);
}
}
@ -157,7 +161,7 @@ public class RedissonSession extends StandardSession {
protected void removeAttributeInternal(String name, boolean notify) {
super.removeAttributeInternal(name, notify);
if (map != null) {
if (updateMode == UpdateMode.DEFAULT && map != null) {
map.fastRemove(name);
}
}

@ -17,12 +17,11 @@ package org.redisson.tomcat;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import org.apache.catalina.Context;
import javax.servlet.http.HttpSession;
import org.apache.catalina.Context;
import org.apache.catalina.LifecycleException;
import org.apache.catalina.LifecycleState;
import org.apache.catalina.Session;
@ -138,7 +137,7 @@ public class RedissonSessionManager extends ManagerBase {
@Override
public Session createEmptySession() {
return new RedissonSession(this, readMode);
return new RedissonSession(this, readMode, updateMode);
}
@Override
@ -213,18 +212,14 @@ public class RedissonSessionManager extends ManagerBase {
}
public void store(HttpSession session) {
public void store(HttpSession session) throws IOException {
if (session == null) {
return;
}
if (updateMode == UpdateMode.AFTER_REQUEST) {
Enumeration<String> names = session.getAttributeNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Object value = session.getAttribute(name);
session.setAttribute(name, value);
}
RedissonSession sess = (RedissonSession) findSession(session.getId());
sess.save();
}
}

@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.catalina.session.StandardSession;
import org.redisson.api.RMap;
import org.redisson.tomcat.RedissonSessionManager.ReadMode;
import org.redisson.tomcat.RedissonSessionManager.UpdateMode;
/**
* Redisson Session object for Apache Tomcat
@ -37,11 +38,13 @@ public class RedissonSession extends StandardSession {
private final Map<String, Object> attrs;
private RMap<String, Object> map;
private final RedissonSessionManager.ReadMode readMode;
private final UpdateMode updateMode;
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode) {
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode, UpdateMode updateMode) {
super(manager);
this.redissonManager = manager;
this.readMode = readMode;
this.updateMode = updateMode;
try {
Field attr = StandardSession.class.getDeclaredField("attributes");
@ -149,7 +152,7 @@ public class RedissonSession extends StandardSession {
public void setAttribute(String name, Object value, boolean notify) {
super.setAttribute(name, value, notify);
if (map != null && value != null) {
if (updateMode == UpdateMode.DEFAULT && map != null && value != null) {
map.fastPut(name, value);
}
}
@ -158,7 +161,7 @@ public class RedissonSession extends StandardSession {
protected void removeAttributeInternal(String name, boolean notify) {
super.removeAttributeInternal(name, notify);
if (map != null) {
if (updateMode == UpdateMode.DEFAULT && map != null) {
map.fastRemove(name);
}
}

@ -17,7 +17,6 @@ package org.redisson.tomcat;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpSession;
@ -138,7 +137,7 @@ public class RedissonSessionManager extends ManagerBase {
@Override
public Session createEmptySession() {
return new RedissonSession(this, readMode);
return new RedissonSession(this, readMode, updateMode);
}
@Override
@ -208,18 +207,14 @@ public class RedissonSessionManager extends ManagerBase {
}
public void store(HttpSession session) {
public void store(HttpSession session) throws IOException {
if (session == null) {
return;
}
if (updateMode == UpdateMode.AFTER_REQUEST) {
Enumeration<String> names = session.getAttributeNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Object value = session.getAttribute(name);
session.setAttribute(name, value);
}
RedissonSession sess = (RedissonSession) findSession(session.getId());
sess.save();
}
}

@ -24,6 +24,7 @@ import java.util.concurrent.TimeUnit;
import org.apache.catalina.session.StandardSession;
import org.redisson.api.RMap;
import org.redisson.tomcat.RedissonSessionManager.ReadMode;
import org.redisson.tomcat.RedissonSessionManager.UpdateMode;
/**
* Redisson Session object for Apache Tomcat
@ -37,11 +38,13 @@ public class RedissonSession extends StandardSession {
private final Map<String, Object> attrs;
private RMap<String, Object> map;
private final RedissonSessionManager.ReadMode readMode;
private final UpdateMode updateMode;
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode) {
public RedissonSession(RedissonSessionManager manager, RedissonSessionManager.ReadMode readMode, UpdateMode updateMode) {
super(manager);
this.redissonManager = manager;
this.readMode = readMode;
this.updateMode = updateMode;
try {
Field attr = StandardSession.class.getDeclaredField("attributes");
@ -149,7 +152,7 @@ public class RedissonSession extends StandardSession {
public void setAttribute(String name, Object value, boolean notify) {
super.setAttribute(name, value, notify);
if (map != null && value != null) {
if (updateMode == UpdateMode.DEFAULT && map != null && value != null) {
map.fastPut(name, value);
}
}
@ -158,7 +161,7 @@ public class RedissonSession extends StandardSession {
protected void removeAttributeInternal(String name, boolean notify) {
super.removeAttributeInternal(name, notify);
if (map != null) {
if (updateMode == UpdateMode.DEFAULT && map != null) {
map.fastRemove(name);
}
}

@ -17,7 +17,6 @@ package org.redisson.tomcat;
import java.io.File;
import java.io.IOException;
import java.util.Enumeration;
import java.util.Map;
import javax.servlet.http.HttpSession;
@ -138,7 +137,7 @@ public class RedissonSessionManager extends ManagerBase {
@Override
public Session createEmptySession() {
return new RedissonSession(this, readMode);
return new RedissonSession(this, readMode, updateMode);
}
@Override
@ -208,18 +207,14 @@ public class RedissonSessionManager extends ManagerBase {
}
public void store(HttpSession session) {
public void store(HttpSession session) throws IOException {
if (session == null) {
return;
}
if (updateMode == UpdateMode.AFTER_REQUEST) {
Enumeration<String> names = session.getAttributeNames();
while (names.hasMoreElements()) {
String name = names.nextElement();
Object value = session.getAttribute(name);
session.setAttribute(name, value);
}
RedissonSession sess = (RedissonSession) findSession(session.getId());
sess.save();
}
}

@ -170,7 +170,7 @@
<dependency>
<groupId>com.esotericsoftware</groupId>
<artifactId>kryo</artifactId>
<version>3.0.3</version>
<version>4.0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
@ -248,6 +248,13 @@
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework</groupId>
<artifactId>spring-tx</artifactId>
<version>[3.1,5.0)</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.springframework.session</groupId>
<artifactId>spring-session-core</artifactId>

@ -19,6 +19,7 @@ import java.math.BigDecimal;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.concurrent.TimeUnit;
import org.redisson.api.RBitSetAsync;
import org.redisson.api.RBloomFilter;
@ -54,15 +55,18 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF
private volatile int hashIterations;
private final CommandExecutor commandExecutor;
private final String configName;
protected RedissonBloomFilter(CommandExecutor commandExecutor, String name) {
super(commandExecutor, name);
this.commandExecutor = commandExecutor;
this.configName = suffixName(getName(), "config");
}
protected RedissonBloomFilter(Codec codec, CommandExecutor commandExecutor, String name) {
super(codec, commandExecutor, name);
this.commandExecutor = commandExecutor;
this.configName = suffixName(getName(), "config");
}
private int optimalNumOfHashFunctions(long n, long m) {
@ -179,18 +183,18 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF
}
private void addConfigCheck(int hashIterations, long size, CommandBatchService executorService) {
executorService.evalReadAsync(getConfigName(), codec, RedisCommands.EVAL_VOID,
executorService.evalReadAsync(configName, codec, RedisCommands.EVAL_VOID,
"local size = redis.call('hget', KEYS[1], 'size');" +
"local hashIterations = redis.call('hget', KEYS[1], 'hashIterations');" +
"assert(size == ARGV[1] and hashIterations == ARGV[2], 'Bloom filter config has been changed')",
Arrays.<Object>asList(getConfigName()), size, hashIterations);
Arrays.<Object>asList(configName), size, hashIterations);
}
@Override
public long count() {
CommandBatchService executorService = new CommandBatchService(commandExecutor.getConnectionManager());
RFuture<Map<String, String>> configFuture = executorService.readAsync(getConfigName(), StringCodec.INSTANCE,
new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder()), getConfigName());
RFuture<Map<String, String>> configFuture = executorService.readAsync(configName, StringCodec.INSTANCE,
new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder()), configName);
RBitSetAsync bs = createBitSet(executorService);
RFuture<Long> cardinalityFuture = bs.cardinalityAsync();
executorService.execute();
@ -202,12 +206,12 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF
@Override
public RFuture<Boolean> deleteAsync() {
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), getConfigName());
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), configName);
}
private void readConfig() {
RFuture<Map<String, String>> future = commandExecutor.readAsync(getConfigName(), StringCodec.INSTANCE,
new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder()), getConfigName());
RFuture<Map<String, String>> future = commandExecutor.readAsync(configName, StringCodec.INSTANCE,
new RedisCommand<Map<Object, Object>>("HGETALL", new ObjectMapReplayDecoder()), configName);
Map<String, String> config = commandExecutor.get(future);
readConfig(config);
@ -245,13 +249,13 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF
hashIterations = optimalNumOfHashFunctions(expectedInsertions, size);
CommandBatchService executorService = new CommandBatchService(commandExecutor.getConnectionManager());
executorService.evalReadAsync(getConfigName(), codec, RedisCommands.EVAL_VOID,
executorService.evalReadAsync(configName, codec, RedisCommands.EVAL_VOID,
"local size = redis.call('hget', KEYS[1], 'size');" +
"local hashIterations = redis.call('hget', KEYS[1], 'hashIterations');" +
"assert(size == false and hashIterations == false, 'Bloom filter config has been changed')",
Arrays.<Object>asList(getConfigName()), size, hashIterations);
executorService.writeAsync(getConfigName(), StringCodec.INSTANCE,
new RedisCommand<Void>("HMSET", new VoidReplayConvertor()), getConfigName(),
Arrays.<Object>asList(configName), size, hashIterations);
executorService.writeAsync(configName, StringCodec.INSTANCE,
new RedisCommand<Void>("HMSET", new VoidReplayConvertor()), configName,
"size", size, "hashIterations", hashIterations,
"expectedInsertions", expectedInsertions, "falseProbability", BigDecimal.valueOf(falseProbability).toPlainString());
try {
@ -267,31 +271,53 @@ public class RedissonBloomFilter<T> extends RedissonExpirable implements RBloomF
return true;
}
private String getConfigName() {
return suffixName(getName(), "config");
@Override
public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return redis.call('pexpire', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(getName(), configName),
timeUnit.toMillis(timeToLive));
}
@Override
public RFuture<Boolean> expireAtAsync(long timestamp) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpireat', KEYS[1], ARGV[1]); " +
"return redis.call('pexpireat', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(getName(), configName),
timestamp);
}
@Override
public RFuture<Boolean> clearExpireAsync() {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('persist', KEYS[1]); " +
"return redis.call('persist', KEYS[2]); ",
Arrays.<Object>asList(getName(), configName));
}
@Override
public long getExpectedInsertions() {
Long result = commandExecutor.read(getConfigName(), LongCodec.INSTANCE, RedisCommands.HGET, getConfigName(), "expectedInsertions");
Long result = commandExecutor.read(configName, LongCodec.INSTANCE, RedisCommands.HGET, configName, "expectedInsertions");
return check(result);
}
@Override
public double getFalseProbability() {
Double result = commandExecutor.read(getConfigName(), DoubleCodec.INSTANCE, RedisCommands.HGET, getConfigName(), "falseProbability");
Double result = commandExecutor.read(configName, DoubleCodec.INSTANCE, RedisCommands.HGET, configName, "falseProbability");
return check(result);
}
@Override
public long getSize() {
Long result = commandExecutor.read(getConfigName(), LongCodec.INSTANCE, RedisCommands.HGET, getConfigName(), "size");
Long result = commandExecutor.read(configName, LongCodec.INSTANCE, RedisCommands.HGET, configName, "size");
return check(result);
}
@Override
public int getHashIterations() {
Integer result = commandExecutor.read(getConfigName(), IntegerCodec.INSTANCE, RedisCommands.HGET, getConfigName(), "hashIterations");
Integer result = commandExecutor.read(configName, IntegerCodec.INSTANCE, RedisCommands.HGET, configName, "hashIterations");
return check(result);
}

@ -33,7 +33,6 @@ import org.redisson.command.CommandAsyncExecutor;
import org.redisson.misc.RedissonPromise;
import io.netty.util.internal.PlatformDependent;
import io.netty.util.internal.ThreadLocalRandom;
/**
*
@ -44,9 +43,15 @@ import io.netty.util.internal.ThreadLocalRandom;
public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelayedQueue<V> {
private final QueueTransferService queueTransferService;
private final String channelName;
private final String queueName;
private final String timeoutSetName;
protected RedissonDelayedQueue(QueueTransferService queueTransferService, Codec codec, final CommandAsyncExecutor commandExecutor, String name) {
super(codec, commandExecutor, name);
channelName = prefixName("redisson_delay_queue_channel", getName());
queueName = prefixName("redisson_delay_queue", getName());
timeoutSetName = prefixName("redisson_delay_queue_timeout", getName());
QueueTransferTask task = new QueueTransferTask(commandExecutor.getConnectionManager()) {
@ -68,33 +73,21 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "return v[2]; "
+ "end "
+ "return nil;",
Arrays.<Object>asList(getName(), getTimeoutSetName(), getQueueName()),
Arrays.<Object>asList(getName(), timeoutSetName, queueName),
System.currentTimeMillis(), 100);
}
@Override
protected RTopic<Long> getTopic() {
return new RedissonTopic<Long>(LongCodec.INSTANCE, commandExecutor, getChannelName());
return new RedissonTopic<Long>(LongCodec.INSTANCE, commandExecutor, channelName);
}
};
queueTransferService.schedule(getQueueName(), task);
queueTransferService.schedule(queueName, task);
this.queueTransferService = queueTransferService;
}
private String getChannelName() {
return prefixName("redisson_delay_queue_channel", getName());
}
private String getQueueName() {
return prefixName("redisson_delay_queue", getName());
}
private String getTimeoutSetName() {
return prefixName("redisson_delay_queue_timeout", getName());
}
public void offer(V e, long delay, TimeUnit timeUnit) {
get(offerAsync(e, delay, timeUnit));
}
@ -115,7 +108,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "redis.call('publish', KEYS[4], ARGV[1]); "
+ "end;"
,
Arrays.<Object>asList(getName(), getTimeoutSetName(), getQueueName(), getChannelName()),
Arrays.<Object>asList(getName(), timeoutSetName, queueName, channelName),
timeout, randomId, encode(e));
}
@ -180,7 +173,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "return value; "
+ "end "
+ "return nil;",
Arrays.<Object>asList(getQueueName()), index));
Arrays.<Object>asList(queueName), index));
}
void remove(int index) {
@ -191,7 +184,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
"redis.call('lrem', KEYS[1], 1, v);" +
"redis.call('zrem', KEYS[2], v);" +
"end; ",
Arrays.<Object>asList(getQueueName(), getTimeoutSetName()), index));
Arrays.<Object>asList(queueName, timeoutSetName), index));
}
@Override
@ -268,7 +261,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "table.insert(result, value);"
+ "end; "
+ "return result; ",
Collections.<Object>singletonList(getQueueName()));
Collections.<Object>singletonList(queueName));
}
@Override
@ -294,7 +287,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "end; "
+ "end;" +
"return 0;",
Arrays.<Object>asList(getQueueName(), getTimeoutSetName()), encode(o));
Arrays.<Object>asList(queueName, timeoutSetName), encode(o));
}
@Override
@ -316,7 +309,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "end; "
+ "end;" +
"return #ARGV == 0 and 1 or 0;",
Collections.<Object>singletonList(getQueueName()), encode(c).toArray());
Collections.<Object>singletonList(queueName), encode(c).toArray());
}
@Override
@ -356,7 +349,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "i = i + 1;"
+ "end; "
+ "return result;",
Arrays.<Object>asList(getQueueName(), getTimeoutSetName()), encode(c).toArray());
Arrays.<Object>asList(queueName, timeoutSetName), encode(c).toArray());
}
@Override
@ -395,7 +388,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "i = i + 1; "
+ "end; "
+ "return changed; ",
Collections.<Object>singletonList(getQueueName()), encode(c).toArray());
Collections.<Object>singletonList(queueName), encode(c).toArray());
}
@Override
@ -405,9 +398,36 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
@Override
public RFuture<Boolean> deleteAsync() {
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getQueueName(), getTimeoutSetName());
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, queueName, timeoutSetName);
}
@Override
public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return redis.call('pexpire', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(queueName, timeoutSetName),
timeUnit.toMillis(timeToLive));
}
@Override
public RFuture<Boolean> expireAtAsync(long timestamp) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpireat', KEYS[1], ARGV[1]); " +
"return redis.call('pexpireat', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(queueName, timeoutSetName),
timestamp);
}
@Override
public RFuture<Boolean> clearExpireAsync() {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('persist', KEYS[1]); " +
"return redis.call('persist', KEYS[2]); ",
Arrays.<Object>asList(queueName, timeoutSetName));
}
@Override
public RFuture<V> peekAsync() {
return commandExecutor.evalReadAsync(getName(), codec, RedisCommands.EVAL_OBJECT,
@ -417,7 +437,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "return value; "
+ "end "
+ "return nil;",
Arrays.<Object>asList(getQueueName()));
Arrays.<Object>asList(queueName));
}
@Override
@ -430,7 +450,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "return value; "
+ "end "
+ "return nil;",
Arrays.<Object>asList(getQueueName(), getTimeoutSetName()));
Arrays.<Object>asList(queueName, timeoutSetName));
}
@Override
@ -449,7 +469,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "return value; "
+ "end "
+ "return nil;",
Arrays.<Object>asList(getQueueName(), getTimeoutSetName(), queueName));
Arrays.<Object>asList(this.queueName, timeoutSetName, queueName));
}
@Override
@ -464,12 +484,12 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
+ "end; "
+ "end;" +
"return 0;",
Collections.<Object>singletonList(getQueueName()), encode(o));
Collections.<Object>singletonList(queueName), encode(o));
}
@Override
public RFuture<Integer> sizeAsync() {
return commandExecutor.readAsync(getName(), codec, RedisCommands.LLEN_INT, getQueueName());
return commandExecutor.readAsync(getName(), codec, RedisCommands.LLEN_INT, queueName);
}
@Override
@ -489,7 +509,7 @@ public class RedissonDelayedQueue<V> extends RedissonExpirable implements RDelay
@Override
public void destroy() {
queueTransferService.remove(getQueueName());
queueTransferService.remove(queueName);
}
}

@ -42,18 +42,14 @@ public class RedissonFairLock extends RedissonLock implements RLock {
private final long threadWaitTime = 5000;
private final CommandExecutor commandExecutor;
private final String threadsQueueName;
private final String timeoutSetName;
protected RedissonFairLock(CommandExecutor commandExecutor, String name, UUID id) {
super(commandExecutor, name, id);
this.commandExecutor = commandExecutor;
}
String getThreadsQueueName() {
return prefixName("redisson_lock_queue", getName());
}
String getTimeoutSetName() {
return prefixName("redisson_lock_timeout", getName());
threadsQueueName = prefixName("redisson_lock_queue", name);
timeoutSetName = prefixName("redisson_lock_timeout", name);
}
@Override
@ -85,7 +81,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"end;" +
"redis.call('zrem', KEYS[2], ARGV[1]); " +
"redis.call('lrem', KEYS[1], 0, ARGV[1]); ",
Arrays.<Object>asList(getThreadsQueueName(), getTimeoutSetName()),
Arrays.<Object>asList(threadsQueueName, timeoutSetName),
getLockName(threadId), threadWaitTime);
}
@ -126,7 +122,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"return nil; " +
"end; " +
"return 1;",
Arrays.<Object>asList(getName(), getThreadsQueueName(), getTimeoutSetName()),
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName),
internalLockLeaseTime, getLockName(threadId), currentTime);
}
@ -174,7 +170,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"redis.call('rpush', KEYS[2], ARGV[2]);" +
"end; " +
"return ttl;",
Arrays.<Object>asList(getName(), getThreadsQueueName(), getTimeoutSetName()),
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName),
internalLockLeaseTime, getLockName(threadId), currentTime + threadWaitTime, currentTime);
}
@ -221,7 +217,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"redis.call('publish', KEYS[4] .. ':' .. nextThreadId, ARGV[1]); " +
"end; " +
"return 1; ",
Arrays.<Object>asList(getName(), getThreadsQueueName(), getTimeoutSetName(), getChannelName()),
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName, getChannelName()),
LockPubSub.unlockMessage, internalLockLeaseTime, getLockName(threadId), System.currentTimeMillis());
}
@ -232,9 +228,39 @@ public class RedissonFairLock extends RedissonLock implements RLock {
@Override
public RFuture<Boolean> deleteAsync() {
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), getThreadsQueueName(), getTimeoutSetName());
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), threadsQueueName, timeoutSetName);
}
@Override
public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"redis.call('pexpire', KEYS[2], ARGV[1]); " +
"return redis.call('pexpire', KEYS[3], ARGV[1]); ",
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName),
timeUnit.toMillis(timeToLive));
}
@Override
public RFuture<Boolean> expireAtAsync(long timestamp) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpireat', KEYS[1], ARGV[1]); " +
"redis.call('pexpireat', KEYS[2], ARGV[1]); " +
"return redis.call('pexpireat', KEYS[3], ARGV[1]); ",
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName),
timestamp);
}
@Override
public RFuture<Boolean> clearExpireAsync() {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('persist', KEYS[1]); " +
"redis.call('persist', KEYS[2]); " +
"return redis.call('persist', KEYS[3]); ",
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName));
}
@Override
public RFuture<Boolean> forceUnlockAsync() {
cancelExpirationRenewal();
@ -263,7 +289,7 @@ public class RedissonFairLock extends RedissonLock implements RLock {
"return 1; " +
"end; " +
"return 0;",
Arrays.<Object>asList(getName(), getThreadsQueueName(), getTimeoutSetName(), getChannelName()),
Arrays.<Object>asList(getName(), threadsQueueName, timeoutSetName, getChannelName()),
LockPubSub.unlockMessage, System.currentTimeMillis());
}

@ -180,8 +180,8 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
private RTopic<Object> invalidationTopic;
private Cache<CacheKey, CacheValue> cache;
private int invalidateEntryOnChange;
private int invalidationListenerId;
private int invalidationStatusListenerId;
private int syncListenerId;
private int reconnectionListenerId;
private volatile long lastInvalidate;
private SyncStrategy syncStrategy;
private final Codec topicCodec = new LocalCachedMessageCodec();
@ -218,7 +218,7 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
invalidationTopic = new RedissonTopic<Object>(topicCodec, commandExecutor, suffixName(name, "topic"));
if (options.getReconnectionStrategy() != ReconnectionStrategy.NONE) {
invalidationStatusListenerId = invalidationTopic.addListener(new BaseStatusListener() {
reconnectionListenerId = invalidationTopic.addListener(new BaseStatusListener() {
@Override
public void onSubscribe(String channel) {
if (options.getReconnectionStrategy() == ReconnectionStrategy.CLEAR) {
@ -272,7 +272,7 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
}
if (options.getSyncStrategy() != SyncStrategy.NONE) {
invalidationListenerId = invalidationTopic.addListener(new MessageListener<Object>() {
syncListenerId = invalidationTopic.addListener(new MessageListener<Object>() {
@Override
public void onMessage(String channel, Object msg) {
if (msg instanceof LocalCachedMapClear) {
@ -481,11 +481,11 @@ public class RedissonLocalCachedMap<K, V> extends RedissonMap<K, V> implements R
@Override
public void destroy() {
if (invalidationListenerId != 0) {
invalidationTopic.removeListener(invalidationListenerId);
if (syncListenerId != 0) {
invalidationTopic.removeListener(syncListenerId);
}
if (invalidationStatusListenerId != 0) {
invalidationTopic.removeListener(invalidationStatusListenerId);
if (reconnectionListenerId != 0) {
invalidationTopic.removeListener(reconnectionListenerId);
}
}

@ -970,6 +970,47 @@ public class RedissonMapCache<K, V> extends RedissonMap<K, V> implements RMapCac
System.currentTimeMillis(), ttlTimeout, maxIdleTimeout, maxIdleDelta, encodeMapKey(key), encodeMapValue(value));
return future;
}
@Override
public long remainTimeToLive(K key) {
return get(remainTimeToLiveAsync(key));
}
@Override
public RFuture<Long> remainTimeToLiveAsync(K key) {
checkKey(key);
return commandExecutor.evalWriteAsync(getName(key), codec, RedisCommands.EVAL_LONG,
"local value = redis.call('hget', KEYS[1], ARGV[2]); "
+ "if value == false then "
+ "return -2; "
+ "end; "
+ "local t, val = struct.unpack('dLc0', value); "
+ "local expireDate = 92233720368547758; " +
"local expireDateScore = redis.call('zscore', KEYS[2], ARGV[2]); "
+ "if expireDateScore ~= false then "
+ "expireDate = tonumber(expireDateScore) "
+ "end; "
+ "if t ~= 0 then "
+ "local expireIdle = redis.call('zscore', KEYS[3], ARGV[2]); "
+ "if expireIdle ~= false then "
+ "expireDate = math.min(expireDate, tonumber(expireIdle)) "
+ "end; "
+ "end; "
+ "if expireDate == 92233720368547758 then "
+ "return -1; "
+ "end;"
+ "if expireDate > tonumber(ARGV[1]) then "
+ "return ARGV[1] - expireDate; "
+ "else "
+ "return -2; "
+ "end; "
+ "return val; ",
Arrays.<Object>asList(getName(key), getTimeoutSetNameByKey(key), getIdleSetNameByKey(key)),
System.currentTimeMillis(), encodeMapKey(key));
}
String getTimeoutSetNameByKey(Object key) {
return prefixName("redisson__timeout__set", getName(key));

@ -53,7 +53,7 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
protected RedissonPermitExpirableSemaphore(CommandExecutor commandExecutor, String name, SemaphorePubSub semaphorePubSub) {
super(commandExecutor, name);
this.timeoutName = "{" + name + "}:timeout";
this.timeoutName = suffixName(name, "timeout");
this.commandExecutor = commandExecutor;
this.semaphorePubSub = semaphorePubSub;
}
@ -635,6 +635,32 @@ public class RedissonPermitExpirableSemaphore extends RedissonExpirable implemen
return commandExecutor.writeAsync(getName(), RedisCommands.DEL_OBJECTS, getName(), timeoutName);
}
@Override
public RFuture<Boolean> expireAsync(long timeToLive, TimeUnit timeUnit) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpire', KEYS[1], ARGV[1]); " +
"return redis.call('pexpire', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(getName(), timeoutName),
timeUnit.toMillis(timeToLive));
}
@Override
public RFuture<Boolean> expireAtAsync(long timestamp) {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('pexpireat', KEYS[1], ARGV[1]); " +
"return redis.call('pexpireat', KEYS[2], ARGV[1]); ",
Arrays.<Object>asList(getName(), timeoutName),
timestamp);
}
@Override
public RFuture<Boolean> clearExpireAsync() {
return commandExecutor.evalWriteAsync(getName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
"redis.call('persist', KEYS[1]); " +
"return redis.call('persist', KEYS[2]); ",
Arrays.<Object>asList(getName(), timeoutName));
}
@Override
public RFuture<Void> releaseAsync(final String permitId) {
final RPromise<Void> result = new RedissonPromise<Void>();

@ -64,7 +64,7 @@ public interface RExpirable extends RObject, RExpirableAsync {
boolean clearExpire();
/**
* Remaining time to live of Redisson object that has a timeout
* Remaining time to live of Redisson object that has a timeout
*
* @return time in milliseconds
* -2 if the key does not exist.

@ -64,9 +64,11 @@ public interface RExpirableAsync extends RObjectAsync {
RFuture<Boolean> clearExpireAsync();
/**
* Get remaining time to live of object in seconds.
* Remaining time to live of Redisson object that has a timeout
*
* @return <code>-1</code> if object does not exist or time in seconds
* @return time in milliseconds
* -2 if the key does not exist.
* -1 if the key exists but has no associated expire.
*/
RFuture<Long> remainTimeToLiveAsync();

@ -260,5 +260,14 @@ public interface RMapCache<K, V> extends RMap<K, V>, RMapCacheAsync<K, V> {
* @param listenerId - listener id
*/
void removeListener(int listenerId);
/**
* Remaining time to live of map entry associated with a <code>key</code>.
*
* @return time in milliseconds
* -2 if the key does not exist.
* -1 if the key exists but has no associated expire.
*/
long remainTimeToLive(K key);
}

@ -220,4 +220,14 @@ public interface RMapCacheAsync<K, V> extends RMapAsync<K, V> {
*/
@Override
RFuture<Integer> sizeAsync();
/**
* Remaining time to live of map entry associated with a <code>key</code>.
*
* @return time in milliseconds
* -2 if the key does not exist.
* -1 if the key exists but has no associated expire.
*/
RFuture<Long> remainTimeToLiveAsync(K key);
}

@ -136,7 +136,14 @@ public class DNSMonitor {
log.info("Detected DNS change. Slave {} has changed ip from {} to {}",
entry.getKey().getHost(), currentSlaveAddr.getAddress().getHostAddress(), newSlaveAddr.getAddress().getHostAddress());
for (final MasterSlaveEntry masterSlaveEntry : connectionManager.getEntrySet()) {
if (masterSlaveEntry.hasSlave(currentSlaveAddr)) {
if (!masterSlaveEntry.hasSlave(currentSlaveAddr)) {
continue;
}
if (masterSlaveEntry.hasSlave(newSlaveAddr)) {
masterSlaveEntry.slaveUp(newSlaveAddr, FreezeReason.MANAGER);
masterSlaveEntry.slaveDown(currentSlaveAddr, FreezeReason.MANAGER);
} else {
RFuture<Void> addFuture = masterSlaveEntry.addSlave(newSlaveAddr, entry.getKey());
addFuture.addListener(new FutureListener<Void>() {
@Override
@ -149,8 +156,8 @@ public class DNSMonitor {
masterSlaveEntry.slaveDown(currentSlaveAddr, FreezeReason.MANAGER);
}
});
break;
}
break;
}
slaves.put(entry.getKey(), newSlaveAddr);
}

@ -428,7 +428,7 @@ public class MasterSlaveEntry {
// exclude master from slaves
if (!config.checkSkipSlavesInit()
&& !addr.equals(entry.getClient().getAddr())) {
slaveDown(masterEntry.getClient().getAddr(), FreezeReason.SYSTEM);
slaveDown(addr, FreezeReason.SYSTEM);
log.info("master {} excluded from slaves", addr);
}
return true;
@ -443,11 +443,27 @@ public class MasterSlaveEntry {
// exclude master from slaves
if (!config.checkSkipSlavesInit()
&& !URIBuilder.compare(addr, address)) {
slaveDown(masterEntry.getClient().getAddr(), FreezeReason.SYSTEM);
slaveDown(addr, FreezeReason.SYSTEM);
log.info("master {} excluded from slaves", addr);
}
return true;
}
public boolean slaveUp(InetSocketAddress address, FreezeReason freezeReason) {
if (!slaveBalancer.unfreeze(address, freezeReason)) {
return false;
}
InetSocketAddress addr = masterEntry.getClient().getAddr();
// exclude master from slaves
if (!config.checkSkipSlavesInit()
&& !addr.equals(address)) {
slaveDown(addr, FreezeReason.SYSTEM);
log.info("master {} excluded from slaves", addr);
}
return true;
}
/**
* Freeze slave with <code>redis(s)://host:port</code> from slaves list.

@ -16,7 +16,6 @@
package org.redisson.spring.cache;
import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.util.concurrent.Callable;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicLong;
@ -47,10 +46,9 @@ public class RedissonCache implements Cache {
private final AtomicLong misses = new AtomicLong();
public RedissonCache(RMapCache<Object, Object> mapCache, CacheConfig config, boolean allowNullValues) {
this(mapCache, allowNullValues);
this.mapCache = mapCache;
this.map = mapCache;
this.config = config;
this.allowNullValues = allowNullValues;
}
public RedissonCache(RMap<Object, Object> map, boolean allowNullValues) {
@ -98,11 +96,7 @@ public class RedissonCache implements Cache {
@Override
public void put(Object key, Object value) {
if (!allowNullValues && value == null) {
if (mapCache != null) {
mapCache.remove(key);
} else {
map.remove(key);
}
map.remove(key);
return;
}
@ -117,11 +111,7 @@ public class RedissonCache implements Cache {
public ValueWrapper putIfAbsent(Object key, Object value) {
Object prevValue;
if (!allowNullValues && value == null) {
if (mapCache != null) {
prevValue = mapCache.get(key);
} else {
prevValue = map.get(key);
}
prevValue = map.get(key);
} else {
value = toStoreValue(value);
if (mapCache != null) {

@ -57,6 +57,19 @@ public class RedissonMapCacheTest extends BaseMapTest {
return redisson.getMapCache("test", options);
}
@Test
public void testRemainTimeToLive() {
RMapCache<String, String> map = redisson.getMapCache("test");
map.put("1", "2", 2, TimeUnit.SECONDS);
assertThat(map.remainTimeToLive("1")).isLessThan(1900);
map.put("3", "4");
assertThat(map.remainTimeToLive("3")).isEqualTo(-1);
assertThat(map.remainTimeToLive("0")).isEqualTo(-2);
map.put("5", "6", 20, TimeUnit.SECONDS, 10, TimeUnit.SECONDS);
assertThat(map.remainTimeToLive("1")).isLessThan(9900);
}
@Test
public void testWriterPutIfAbsentTTL() {
Map<String, String> store = new HashMap<>();

Loading…
Cancel
Save