Please wait. This can take some minutes ...
Many resources are needed to download a project. Please understand that we have to compensate our server costs. Thank you in advance.
Project price only 1 $
You can buy this project and download/modify it how often you want.
com.github.lontime.extredisson.cache.Redisson2LevelMapCache Maven / Gradle / Ivy
package com.github.lontime.extredisson.cache;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.AbstractMap;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.CompletionStage;
import java.util.concurrent.ConcurrentMap;
import java.util.concurrent.ThreadLocalRandom;
import java.util.concurrent.TimeUnit;
import com.github.lontime.base.logging.GLogger;
import io.netty.buffer.ByteBuf;
import com.github.lontime.shaded.org.redisson.RedissonMapCache;
import com.github.lontime.shaded.org.redisson.WriteBehindService;
import com.github.lontime.shaded.org.redisson.api.LocalCachedMapOptions;
import com.github.lontime.shaded.org.redisson.api.RFuture;
import com.github.lontime.shaded.org.redisson.api.RedissonClient;
import com.github.lontime.shaded.org.redisson.cache.CacheKey;
import com.github.lontime.shaded.org.redisson.cache.CacheValue;
import com.github.lontime.shaded.org.redisson.cache.LocalCacheListener;
import com.github.lontime.shaded.org.redisson.cache.LocalCachedMapClear;
import com.github.lontime.shaded.org.redisson.cache.LocalCachedMapInvalidate;
import com.github.lontime.shaded.org.redisson.cache.LocalCachedMapUpdate;
import com.github.lontime.shaded.org.redisson.cache.LocalCachedMessageCodec;
import com.github.lontime.shaded.org.redisson.client.codec.Codec;
import com.github.lontime.shaded.org.redisson.client.codec.LongCodec;
import com.github.lontime.shaded.org.redisson.client.codec.StringCodec;
import com.github.lontime.shaded.org.redisson.client.protocol.RedisCommand;
import com.github.lontime.shaded.org.redisson.client.protocol.RedisCommands;
import com.github.lontime.shaded.org.redisson.client.protocol.convertor.NumberConvertor;
import com.github.lontime.shaded.org.redisson.command.CommandAsyncExecutor;
import com.github.lontime.shaded.org.redisson.eviction.EvictionScheduler;
import com.github.lontime.shaded.org.redisson.misc.CompletableFutureWrapper;
/**
* Redisson2LevelMapCache.
* 先通知 在执行具体的操作.有可能引起 错误通知,不过可以保证redis数据正确
*
* @author lontime
* @since 1.0
* @param K
* @param V
*/
@SuppressWarnings("all")
public class Redisson2LevelMapCache extends RedissonMapCache implements R2LevelMapCache {
public static final String HOLDER_VALUE = "x";
private long cacheUpdateLogTime = TimeUnit.MINUTES.toMillis(10);
private byte[] instanceId;
private ConcurrentMap cache;
private int invalidateEntryOnChange;
private LocalCachedMapOptions.SyncStrategy syncStrategy;
private LocalCachedMapOptions.StoreMode storeMode;
private boolean storeCacheMiss;
private LocalCacheListener listener;
private ExtLocalCacheView localCacheView;
public Redisson2LevelMapCache(CommandAsyncExecutor commandExecutor, String name, LocalCachedMapOptions options,
EvictionScheduler evictionScheduler, RedissonClient redisson, WriteBehindService writeBehindService) {
super(evictionScheduler, commandExecutor, name, redisson, options, writeBehindService);
init(options, redisson, evictionScheduler);
}
public Redisson2LevelMapCache(Codec codec, CommandAsyncExecutor connectionManager, String name, LocalCachedMapOptions options,
EvictionScheduler evictionScheduler, RedissonClient redisson, WriteBehindService writeBehindService) {
super(codec, evictionScheduler, connectionManager, name, redisson, options, writeBehindService);
init(options, redisson, evictionScheduler);
}
private void init(LocalCachedMapOptions options, RedissonClient redisson, EvictionScheduler evictionScheduler) {
syncStrategy = options.getSyncStrategy();
storeMode = options.getStoreMode();
storeCacheMiss = options.isStoreCacheMiss();
localCacheView = new ExtLocalCacheView<>(options, this);
cache = localCacheView.getCache();
listener = new LocalCacheListener(getLocalRawName(), commandExecutor, this, codec, options, cacheUpdateLogTime) {
@Override
protected void updateCache(ByteBuf keyBuf, ByteBuf valueBuf) throws IOException {
CacheKey cacheKey = localCacheView.toCacheKey(keyBuf);
Object key = codec.getMapKeyDecoder().decode(keyBuf, null);
Object value = codec.getMapValueDecoder().decode(valueBuf, null);
cachePut(cacheKey, key, value);
}
};
listener.add(cache);
instanceId = listener.getInstanceId();
if (options.getSyncStrategy() != LocalCachedMapOptions.SyncStrategy.NONE) {
invalidateEntryOnChange = 1;
}
if (options.getReconnectionStrategy() == LocalCachedMapOptions.ReconnectionStrategy.LOAD) {
invalidateEntryOnChange = 2;
evictionScheduler.schedule(listener.getUpdatesLogName(), cacheUpdateLogTime + TimeUnit.MINUTES.toMillis(1));
}
}
public ExtLocalCacheView getLocalCacheView() {
return localCacheView;
}
private void broadcastLocalCacheStore(V value, ByteBuf mapKey, CacheKey cacheKey) {
if (storeMode != LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return;
}
if (invalidateEntryOnChange != 0) {
Object msg;
if (syncStrategy == LocalCachedMapOptions.SyncStrategy.UPDATE) {
ByteBuf mapValue = encodeMapValue(value);
msg = new LocalCachedMapUpdate(instanceId, mapKey, mapValue);
} else {
msg = new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash());
}
listener.getInvalidationTopic().publishAsync(msg);
}
mapKey.release();
}
private CacheValue cachePut(CacheKey cacheKey, Object key, Object value) {
if (listener.isDisabled(cacheKey)) {
return null;
}
return cache.put(cacheKey, new CacheValue(key, value));
}
private CacheValue cachePutIfAbsent(CacheKey cacheKey, Object key, Object value) {
if (listener.isDisabled(cacheKey)) {
return null;
}
return cache.putIfAbsent(cacheKey, new CacheValue(key, value));
}
private CacheValue cachePutIfExists(CacheKey cacheKey, Object key, Object value) {
if (listener.isDisabled(cacheKey)) {
return null;
}
while (true) {
CacheValue v = cache.get(cacheKey);
if (v != null) {
if (cache.replace(cacheKey, v, new CacheValue(key, value))) {
return v;
}
} else {
return null;
}
}
}
private CacheValue cacheReplace(CacheKey cacheKey, Object key, Object value) {
if (listener.isDisabled(cacheKey)) {
return null;
}
return cache.replace(cacheKey, new CacheValue(key, value));
}
private boolean cacheReplace(CacheKey cacheKey, Object key, Object oldValue, Object newValue) {
if (listener.isDisabled(cacheKey)) {
return false;
}
return cache.replace(cacheKey, new CacheValue(key, oldValue), new CacheValue(key, newValue));
}
private boolean cacheRemove(CacheKey cacheKey, Object key, Object value) {
if (listener.isDisabled(cacheKey)) {
return false;
}
return cache.remove(cacheKey, new CacheValue(key, value));
}
@Override
public RFuture sizeAsync() {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(cache.size());
}
return super.sizeAsync();
}
@Override
public RFuture containsKeyAsync(Object key) {
checkKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(key);
CacheValue cacheValue = cache.get(cacheKey);
if (cacheValue == null) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
if (hasNoLoader()) {
return new CompletableFutureWrapper<>(false);
}
CompletableFuture future = loadValue((K) key, false);
CompletableFuture f = future.thenApply(value -> {
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
return value != null;
});
return new CompletableFutureWrapper<>(f);
}
CompletableFuture promise = new CompletableFuture<>();
promise.thenAccept(value -> {
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
});
return containsKeyAsync(key, promise);
}
return new CompletableFutureWrapper<>(cacheValue.getValue() != null);
}
@Override
public RFuture containsValueAsync(Object value) {
checkValue(value);
CacheValue cacheValue = new CacheValue(null, value);
if (!cache.containsValue(cacheValue)) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(false);
}
return super.containsValueAsync(value);
}
return new CompletableFutureWrapper<>(true);
}
@Override
public RFuture getAsync(Object key) {
checkKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(key);
CacheValue cacheValue = cache.get(cacheKey);
if (cacheValue != null && (storeCacheMiss || cacheValue.getValue() != null)) {
GLogger.defaults().debugv("{0} found in local cache", key);
return new CompletableFutureWrapper<>((V) cacheValue.getValue());
}
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
if (hasNoLoader()) {
return new CompletableFutureWrapper((Void) null);
}
CompletableFuture future = loadValue((K) key, false);
CompletableFuture f = future.thenApply(value -> {
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
return value;
});
return new CompletableFutureWrapper<>(f);
}
RFuture future = super.getAsync((K) key);
CompletionStage result = future.thenApply(value -> {
if (storeCacheMiss || value != null) {
cachePut(cacheKey, key, value);
}
return value;
});
return new CompletableFutureWrapper<>(result);
}
protected static byte[] generateLogEntryId(byte[] keyHash) {
byte[] result = new byte[keyHash.length + 1 + 8];
result[16] = ':';
byte[] id = new byte[8];
ThreadLocalRandom.current().nextBytes(id);
System.arraycopy(keyHash, 0, result, 0, keyHash.length);
System.arraycopy(id, 0, result, 17, id.length);
return result;
}
@Override
protected RFuture putOperationAsync(K key, V value, long ttlTimeout, long maxIdleTimeout,
long maxIdleDelta, long ttlTimeoutDelta) {
//先通知 再放内存
return new CompletableFutureWrapper<>((CompletableFuture) putOperationAsync0(key, value)
.thenCompose(s -> super.putOperationAsync(key, value, ttlTimeout,
maxIdleTimeout, maxIdleDelta, ttlTimeoutDelta)));
}
@Override
protected RFuture putOperationAsync(K key, V value) {
//先通知 再放内存
return new CompletableFutureWrapper<>((CompletableFuture) putOperationAsync0(key, value)
.thenCompose(s -> super.putOperationAsync(key, value)));
}
private RFuture putOperationAsync0(K key, V value) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cachePut(cacheKey, key, value);
broadcastLocalCacheStore(value, mapKey, cacheKey);
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
V val = null;
if (prevValue != null) {
val = (V) prevValue.getValue();
}
return new CompletableFutureWrapper<>(val);
}
ByteBuf mapValue = encodeMapValue(HOLDER_VALUE);
ByteBuf mapValueMessage = encodeMapValue(value);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = createSyncMessage(mapKey, mapValueMessage, cacheKey);
return commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_MAP_VALUE,
//"local v = redis.call('hget', KEYS[1], ARGV[1]); "
//+ "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); "
"if ARGV[4] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[3]); "
+ "end;"
+ "if ARGV[4] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[3]); "
+ "end;"
+ "return 1; "
//+ "return v; ",
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
mapKey, mapValue, msg, invalidateEntryOnChange, System.currentTimeMillis(), entryId);
}
protected ByteBuf createSyncMessage(ByteBuf mapKey, ByteBuf mapValue, CacheKey cacheKey) {
if (syncStrategy == LocalCachedMapOptions.SyncStrategy.UPDATE) {
return encode(new LocalCachedMapUpdate(instanceId, mapKey, mapValue));
}
return encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
}
@Override
protected RFuture fastPutOperationAsync(K key, V value, long ttl, TimeUnit ttlUnit, long maxIdleTime, TimeUnit maxIdleUnit) {
//先通知 再放内存
return new CompletableFutureWrapper<>((CompletableFuture) fastPutOperationAsync0(key, value)
.thenCompose(s -> super.fastPutOperationAsync(key, value, ttl,
ttlUnit, maxIdleTime, maxIdleUnit)));
}
@Override
protected RFuture fastPutOperationAsync(K key, V value) {
//先通知 再放内存
return new CompletableFutureWrapper<>((CompletableFuture) fastPutOperationAsync0(key, value)
.thenCompose(s -> super.fastPutOperationAsync(key, value)));
}
private RFuture fastPutOperationAsync0(K key, V value) {
ByteBuf encodedKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(encodedKey);
CacheValue prevValue = cachePut(cacheKey, key, value);
broadcastLocalCacheStore(value, encodedKey, cacheKey);
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(prevValue == null);
}
ByteBuf encodedValue = encodeMapValue(HOLDER_VALUE);
ByteBuf encodedValueMessage = encodeMapValue(value);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = createSyncMessage(encodedKey, encodedValueMessage, cacheKey);
return commandExecutor.evalWriteAsync(getRawName(),
codec, RedisCommands.EVAL_BOOLEAN,
"if ARGV[4] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[3]); "
+ "end;"
+ "if ARGV[4] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[3]); "
+ "end;"
//+ "if redis.call('hset', KEYS[1], ARGV[1], ARGV[2]) == 0 then "
//+ "return 0; "
//+ "end; "
+ "return 1; "
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
encodedKey, encodedValue, msg, invalidateEntryOnChange, System.currentTimeMillis(), entryId);
}
@Override
public void destroy() {
cache.clear();
listener.remove();
super.destroy();
}
@Override
protected RFuture removeOperationAsync(K key) {
ByteBuf keyEncoded = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
CacheValue value = cache.remove(cacheKey);
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
keyEncoded.release();
LocalCachedMapInvalidate msg = new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash());
listener.getInvalidationTopic().publishAsync(msg);
V val = null;
if (value != null) {
val = (V) value.getValue();
}
return new CompletableFutureWrapper<>(val);
}
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_MAP_VALUE,
//"local v = redis.call('hget', KEYS[1], ARGV[1]); "
//+ "if redis.call('hdel', KEYS[1], ARGV[1]) == 1 then "
"if ARGV[3] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[2]); "
+ "end; "
+ "if ARGV[3] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[4], ARGV[5]);"
+ "redis.call('publish', KEYS[2], ARGV[2]); "
+ "end;"
+ "return 1;"
//+ "end; "
// + "return v",
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyEncoded, msgEncoded, invalidateEntryOnChange, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.removeOperationAsync(key)));
}
@Override
protected RFuture> fastRemoveOperationBatchAsync(@SuppressWarnings("unchecked") K... keys) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(Collections.emptyList());
}
if (invalidateEntryOnChange == 1) {
List params = new ArrayList(keys.length * 2);
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
ByteBuf msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
params.add(msgEncoded);
}
return new CompletableFutureWrapper<>((CompletableFuture>)
commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LIST,
"local result = {}; " +
"for j = 1, #ARGV, 2 do "
// + "local val = redis.call('hdel', KEYS[1], ARGV[j]);"
+ "local val = 1;"
+ "if val == 1 then "
+ "redis.call('publish', KEYS[2], ARGV[j+1]); "
+ "end;"
+ "table.insert(result, val);"
+ "end;"
+ "return result;"
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName()),
params.toArray())
.thenCompose(s -> super.fastRemoveOperationBatchAsync(keys)));
}
if (invalidateEntryOnChange == 2) {
List params = new ArrayList(keys.length * 3);
params.add(System.currentTimeMillis());
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
ByteBuf msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
params.add(msgEncoded);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
params.add(entryId);
}
return new CompletableFutureWrapper<>(
(CompletableFuture>) commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LIST,
"local result = {}; " +
"for j = 2, #ARGV, 3 do "
// + "local val = redis.call('hdel', KEYS[1], ARGV[j]);"
+ "local val = 1;"
+ "if val == 1 then "
+ "redis.call('zadd', KEYS[3], ARGV[1], ARGV[j+2]);"
+ "redis.call('publish', KEYS[2], ARGV[j+1]); "
+ "end;"
+ "table.insert(result, val);"
+ "end;"
+ "return result;"
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
params.toArray())
.thenCompose(s -> super.fastRemoveOperationBatchAsync(keys)));
}
List params = new ArrayList(keys.length);
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
}
RFuture> future = new CompletableFutureWrapper<>(
(CompletableFuture>) commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_LIST,
"local result = {}; " +
"for i = 1, #ARGV, 1 do "
// + "local val = redis.call('hdel', KEYS[1], ARGV[i]); "
+ "local val = 1; "
+ "table.insert(result, val); "
+ "end;"
+ "return result;"
, Arrays.asList(getLocalRawName()), params.toArray())
.thenCompose(s -> super.fastRemoveOperationBatchAsync(keys)));
return future;
}
@Override
protected RFuture fastRemoveOperationAsync(K... keys) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
long count = 0;
for (K k : keys) {
CacheKey cacheKey = localCacheView.toCacheKey(k);
CacheValue val = cache.remove(cacheKey);
if (val != null) {
count++;
LocalCachedMapInvalidate msg = new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash());
listener.getInvalidationTopic().publishAsync(msg);
}
}
return new CompletableFutureWrapper<>(count);
}
if (invalidateEntryOnChange == 1) {
List params = new ArrayList(keys.length * 2);
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
ByteBuf msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
params.add(msgEncoded);
}
return super.fastRemoveOperationAsync(keys);
}
if (invalidateEntryOnChange == 2) {
List params = new ArrayList(keys.length * 3);
params.add(System.currentTimeMillis());
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
ByteBuf msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
params.add(msgEncoded);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
params.add(entryId);
}
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_LONG,
"local counter = 0; " +
"for j = 2, #ARGV, 3 do "
//+ "if redis.call('hdel', KEYS[1], ARGV[j]) == 1 then "
+ "redis.call('zadd', KEYS[3], ARGV[1], ARGV[j+2]);"
+ "redis.call('publish', KEYS[2], ARGV[j+1]); "
+ "counter = counter + 1;"
+ "end;"
//+ "end;"
+ "return counter;"
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
params.toArray())
.thenCompose(s -> super.fastRemoveOperationAsync(keys)));
}
List params = new ArrayList<>(keys.length + 1);
params.add(getLocalRawName());
for (K k : keys) {
ByteBuf keyEncoded = encodeMapKey(k);
params.add(keyEncoded);
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cache.remove(cacheKey);
}
return super.fastRemoveOperationAsync(keys);
}
@Override
public RFuture sizeInMemoryAsync() {
List keys = Arrays.asList(getRawName(), listener.getUpdatesLogName());
return super.sizeInMemoryAsync(keys);
}
@Override
public RFuture deleteAsync() {
cache.clear();
ByteBuf msgEncoded = encode(new LocalCachedMapClear(instanceId, listener.generateId(), false));
return new CompletableFutureWrapper<>((CompletableFuture) super.deleteAsync()
.thenCompose(s -> commandExecutor.evalWriteAsync(getRawName(), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
// "if redis.call('del', KEYS[1], KEYS[3]) > 0 and ARGV[2] ~= '0' then "
"if redis.call('del', KEYS[3]) > 0 and ARGV[2] ~= '0' then "
+ "redis.call('publish', KEYS[2], ARGV[1]); "
+ "return 1;"
+ "end; "
+ "return 0;"
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
msgEncoded, invalidateEntryOnChange)));
}
@Override
public RFuture> getAllAsync(Set keys) {
if (keys.isEmpty()) {
return new CompletableFutureWrapper<>(Collections.emptyMap());
}
Map result = new HashMap();
Set mapKeys = new HashSet(keys);
Set missedKeys = new HashSet<>();
for (Iterator iterator = mapKeys.iterator(); iterator.hasNext(); ) {
K key = iterator.next();
CacheKey cacheKey = localCacheView.toCacheKey(key);
CacheValue value = cache.get(cacheKey);
if (value != null) {
result.put(key, (V) value.getValue());
iterator.remove();
} else {
missedKeys.add(key);
}
}
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
if (hasNoLoader()) {
return new CompletableFutureWrapper<>(result);
}
if (!missedKeys.isEmpty()) {
CompletionStage> f = loadAllAsync(missedKeys, false, 1, result)
.thenApply(r -> result);
return new CompletableFutureWrapper<>(f);
}
return new CompletableFutureWrapper<>(result);
}
RFuture> future = super.getAllAsync(missedKeys);
CompletionStage> f = future.thenApply(map -> {
result.putAll(map);
cacheMap(map);
if (storeCacheMiss) {
missedKeys.stream()
.filter(key -> !map.containsKey(key))
.forEach(key -> {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, null);
});
}
return result;
});
return new CompletableFutureWrapper<>(f);
}
private void cacheMap(Map, ?> map) {
for (java.util.Map.Entry, ?> entry : map.entrySet()) {
CacheKey cacheKey = localCacheView.toCacheKey(entry.getKey());
cachePut(cacheKey, entry.getKey(), entry.getValue());
}
}
@Override
protected RFuture putAllOperationAsync(Map extends K, ? extends V> map) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
for (Entry extends K, ? extends V> entry : map.entrySet()) {
ByteBuf keyEncoded = encodeMapKey(entry.getKey());
CacheKey cacheKey = localCacheView.toCacheKey(keyEncoded);
cachePut(cacheKey, entry.getKey(), entry.getValue());
broadcastLocalCacheStore(entry.getValue(), keyEncoded, cacheKey);
}
return new CompletableFutureWrapper((Void) null);
}
List params = new ArrayList(map.size() * 3);
params.add(invalidateEntryOnChange);
params.add(map.size() * 2);
byte[][] hashes = new byte[map.size()][];
int i = 0;
for (java.util.Map.Entry extends K, ? extends V> t : map.entrySet()) {
ByteBuf mapKey = encodeMapKey(t.getKey());
ByteBuf mapValue = encodeMapValue(HOLDER_VALUE);
params.add(mapKey);
params.add(mapValue);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
hashes[i] = cacheKey.getKeyHash();
i++;
}
ByteBuf msgEncoded = null;
if (syncStrategy == LocalCachedMapOptions.SyncStrategy.UPDATE) {
List entries = new ArrayList();
for (int j = 2; j < params.size(); j += 2) {
ByteBuf key = (ByteBuf) params.get(j);
ByteBuf value = (ByteBuf) params.get(j + 1);
entries.add(new LocalCachedMapUpdate.Entry(key, value));
}
msgEncoded = encode(new LocalCachedMapUpdate(instanceId, entries));
} else if (syncStrategy == LocalCachedMapOptions.SyncStrategy.INVALIDATE) {
msgEncoded = encode(new LocalCachedMapInvalidate(instanceId, hashes));
}
if (invalidateEntryOnChange == 2) {
long time = System.currentTimeMillis();
for (byte[] hash : hashes) {
byte[] entryId = generateLogEntryId(hash);
params.add(time);
params.add(entryId);
}
}
if (msgEncoded != null) {
params.add(msgEncoded);
}
RFuture future = new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(), codec, RedisCommands.EVAL_VOID,
//"for i=3, tonumber(ARGV[2]) + 2, 5000 do "
//+ "redis.call('hmset', KEYS[1], unpack(ARGV, i, math.min(i+4999, tonumber(ARGV[2]) + 2))); "
//+ "end; "
"if ARGV[1] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[#ARGV]); "
+ "end;"
+ "if ARGV[1] == '2' then "
+ "for i=tonumber(ARGV[2]) + 2 + 1, #ARGV - 1, 5000 do "
+ "redis.call('zadd', KEYS[3], unpack(ARGV, i, math.min(i+4999, #ARGV - 1))); "
+ "end; "
+ "redis.call('publish', KEYS[2], ARGV[#ARGV]); "
+ "end;"
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
params.toArray()).thenCompose(s -> super.putAllOperationAsync(map)));
CompletionStage f = future.thenApply(res -> {
cacheMap(map);
return null;
});
return new CompletableFutureWrapper<>(f);
}
@Override
protected RFuture addAndGetOperationAsync(K key, Number value) {
ByteBuf keyState = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(keyState);
ByteBuf msg = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
RFuture future = new CompletableFutureWrapper<>((CompletableFuture) commandExecutor.evalWriteAsync(getRawName(), StringCodec.INSTANCE,
new RedisCommand("EVAL", new NumberConvertor(value.getClass())),
// "local result = redis.call('HINCRBYFLOAT', KEYS[1], ARGV[1], ARGV[2]); "
"if ARGV[3] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "if ARGV[3] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "return 1; "
// + "return result; ",
, Arrays.asList(getLocalRawName(), listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyState, new BigDecimal(value.toString()).toPlainString(), invalidateEntryOnChange, msg, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.addAndGetOperationAsync(key, value)));
CompletionStage f = future.thenApply(res -> {
if (res != null) {
CacheKey cKey = localCacheView.toCacheKey(key);
cachePut(cKey, key, res);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture fastPutIfAbsentAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cachePutIfAbsent(cacheKey, key, value);
if (prevValue == null) {
broadcastLocalCacheStore(value, mapKey, cacheKey);
return new CompletableFutureWrapper<>(true);
} else {
mapKey.release();
return new CompletableFutureWrapper<>(false);
}
}
RFuture future = super.fastPutIfAbsentAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture fastPutIfExistsAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cachePutIfExists(cacheKey, key, value);
if (prevValue != null) {
broadcastLocalCacheStore(value, mapKey, cacheKey);
return new CompletableFutureWrapper<>(true);
} else {
mapKey.release();
return new CompletableFutureWrapper<>(false);
}
}
RFuture future = super.fastPutIfExistsAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture> readAllValuesAsync() {
List result = new ArrayList();
List mapKeys = new ArrayList();
for (CacheValue value : cache.values()) {
if (value == null) {
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
result.add((V) value.getValue());
}
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(result);
}
RFuture> future = super.readAllValuesAsync();
/*new CompletableFutureWrapper<>(
(CompletableFuture>) commandExecutor.evalReadAsync(getRawName(), codec, ALL_VALUES,
"local entries = redis.call('hgetall', KEYS[1]); "
+ "local result = {};"
+ "for j, v in ipairs(entries) do "
+ "if j % 2 ~= 0 then "
+ "local founded = false;"
+ "for i = 1, #ARGV, 1 do "
+ "if ARGV[i] == entries[j] then "
+ "founded = true;"
+ "end;"
+ "end; "
+ "if founded == false then "
+ "table.insert(result, entries[j+1]);"
+ "end;"
+ "end; "
+ "end; "
+ "return result; ",
Arrays.asList(getLocalRawName()),
mapKeys.toArray()).thenCompose(s -> super.readAllValuesAsync()));*/
CompletionStage> f = future.thenApply(res -> {
result.addAll(res);
return result;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture> readAllMapAsync() {
Map result = new HashMap();
List mapKeys = new ArrayList();
for (CacheValue value : cache.values()) {
if (value == null) {
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
result.put((K) value.getKey(), (V) value.getValue());
}
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(result);
}
return super.readAllMapAsync();
// RPromise> promise = new RedissonPromise>();
// RFuture> future = readAll(ALL_MAP, mapKeys, result);
//
// future.onComplete((res, e) -> {
// if (e != null) {
// promise.tryFailure(e);
// return;
// }
//
// for (java.util.Map.Entry entry : res.entrySet()) {
// CacheKey cacheKey = localCacheView.toCacheKey(entry.getKey());
// cachePut(cacheKey, entry.getKey(), entry.getValue());
// }
// result.putAll(res);
// promise.trySuccess(result);
// });
//
// return promise;
}
@Override
public void preloadCache() {
for (Entry entry : super.entrySet()) {
CacheKey cacheKey = localCacheView.toCacheKey(entry.getKey());
cachePut(cacheKey, entry.getKey(), entry.getValue());
}
}
@Override
public void preloadCache(int count) {
for (Entry entry : super.entrySet(count)) {
CacheKey cacheKey = localCacheView.toCacheKey(entry.getKey());
cachePut(cacheKey, entry.getKey(), entry.getValue());
}
}
@Override
public void clearLocalCache() {
get(clearLocalCacheAsync());
}
@Override
public RFuture clearLocalCacheAsync() {
return listener.clearLocalCacheAsync();
}
@Override
public RFuture>> readAllEntrySetAsync() {
Set> result = new HashSet<>();
List mapKeys = new ArrayList<>();
for (CacheValue value : cache.values()) {
if (value == null) {
continue;
}
mapKeys.add(encodeMapKey(value.getKey()));
result.add(new AbstractMap.SimpleEntry<>((K) value.getKey(), (V) value.getValue()));
}
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
return new CompletableFutureWrapper<>(result);
}
return super.readAllEntrySetAsync();
// RPromise>> promise = new RedissonPromise>>();
// RFuture>> future = readAll(ALL_ENTRIES, mapKeys, result);
//
// future.onComplete((res, e) -> {
// if (e != null) {
// promise.tryFailure(e);
// return;
// }
//
// for (java.util.Map.Entry entry : res) {
// CacheKey cacheKey = localCacheView.toCacheKey(entry.getKey());
// cachePut(cacheKey, entry.getKey(), entry.getValue());
// }
// result.addAll(res);
// promise.trySuccess(result);
// });
//
// return promise;
}
// private RFuture readAll(RedisCommand> evalCommandType, List mapKeys, R result) {
// return commandExecutor.evalReadAsync(getRawName(), codec, evalCommandType,
// "local entries = redis.call('hgetall', KEYS[1]); "
// + "local result = {};"
// + "for j, v in ipairs(entries) do "
// + "if j % 2 ~= 0 then "
// + "local founded = false;"
// + "for i = 1, #ARGV, 1 do "
// + "if ARGV[i] == entries[j] then "
// + "founded = true;"
// + "end;"
// + "end; "
// + "if founded == false then "
// + "table.insert(result, entries[j]);"
// + "table.insert(result, entries[j+1]);"
// + "end;"
// + "end; "
// + "end; "
// + "return result; ",
// Arrays.asList(getLocalRawName()),
// mapKeys.toArray());
// }
@Override
public RFuture fastReplaceAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cacheReplace(cacheKey, key, value);
if (prevValue != null) {
broadcastLocalCacheStore(value, mapKey, cacheKey);
return new CompletableFutureWrapper<>(true);
} else {
mapKey.release();
return new CompletableFutureWrapper<>(false);
}
}
RFuture future = super.fastReplaceAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
protected RFuture fastReplaceOperationAsync(K key, V value) {
ByteBuf keyState = encodeMapKey(key);
ByteBuf valueState = encodeMapValue(HOLDER_VALUE);
ByteBuf valueStateMessage = encodeMapValue(value);
CacheKey cacheKey = localCacheView.toCacheKey(keyState);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = createSyncMessage(keyState, valueStateMessage, cacheKey);
String name = getLocalRawName(key);
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(key), codec, RedisCommands.EVAL_BOOLEAN,
//"if redis.call('hexists', KEYS[1], ARGV[1]) == 1 then "
//+ "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); "
"if ARGV[3] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "if ARGV[3] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "return 1; "
//+ "else "
//+ "return 0; "
//+ "end",
, Arrays.asList(name, listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyState, valueState, invalidateEntryOnChange, msg, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.fastReplaceOperationAsync(key, value)));
}
@Override
protected RFuture replaceOperationAsync(K key, V value) {
ByteBuf keyState = encodeMapKey(key);
ByteBuf valueState = encodeMapValue(HOLDER_VALUE);
ByteBuf valueStateMessage = encodeMapValue(value);
CacheKey cacheKey = localCacheView.toCacheKey(keyState);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = createSyncMessage(keyState, valueStateMessage, cacheKey);
String name = getLocalRawName(key);
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(key), codec, RedisCommands.EVAL_MAP_VALUE,
//"if redis.call('hexists', KEYS[1], ARGV[1]) == 1 then "
//+ "local v = redis.call('hget', KEYS[1], ARGV[1]); "
//+ "redis.call('hset', KEYS[1], ARGV[1], ARGV[2]); "
"if ARGV[3] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "if ARGV[3] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "return 1; "
//+ "else "
//+ "return nil; "
//+ "end",
, Arrays.asList(name, listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyState, valueState, invalidateEntryOnChange, msg, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.replaceOperationAsync(key, value)));
}
@Override
public RFuture replaceAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cacheReplace(cacheKey, key, value);
if (prevValue != null) {
broadcastLocalCacheStore(value, mapKey, cacheKey);
return new CompletableFutureWrapper<>((V) prevValue.getValue());
} else {
mapKey.release();
return new CompletableFutureWrapper((Void) null);
}
}
RFuture future = super.replaceAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res != null) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
protected RFuture replaceOperationAsync(K key, V oldValue, V newValue) {
ByteBuf keyState = encodeMapKey(key);
ByteBuf oldValueState = encodeMapValue(HOLDER_VALUE);
ByteBuf newValueState = encodeMapValue(HOLDER_VALUE);
ByteBuf newValueStateMessage = encodeMapValue(newValue);
CacheKey cacheKey = localCacheView.toCacheKey(keyState);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = createSyncMessage(keyState, newValueStateMessage, cacheKey);
String name = getLocalRawName(key);
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(key), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
//"if redis.call('hget', KEYS[1], ARGV[1]) == ARGV[2] then "
//+ "redis.call('hset', KEYS[1], ARGV[1], ARGV[3]); "
"if ARGV[4] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[5]); "
+ "end;"
+ "if ARGV[4] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[6], ARGV[7]);"
+ "redis.call('publish', KEYS[2], ARGV[5]); "
+ "end;"
+ "return 1; "
//+ "else "
//+ "return 0; "
//+ "end",
, Arrays.asList(name, listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyState, oldValueState, newValueState, invalidateEntryOnChange, msg, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.replaceOperationAsync(key, oldValue, newValue)));
}
@Override
public RFuture replaceAsync(K key, V oldValue, V newValue) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
if (cacheReplace(cacheKey, key, oldValue, newValue)) {
broadcastLocalCacheStore(newValue, mapKey, cacheKey);
return new CompletableFutureWrapper<>(true);
} else {
mapKey.release();
return new CompletableFutureWrapper<>(false);
}
}
RFuture future = super.replaceAsync(key, oldValue, newValue);
CompletionStage f = future.thenApply(res -> {
if (res) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, newValue);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
protected RFuture removeOperationAsync(Object key, Object value) {
ByteBuf keyState = encodeMapKey(key);
ByteBuf valueState = encodeMapValue(HOLDER_VALUE);
CacheKey cacheKey = localCacheView.toCacheKey(keyState);
byte[] entryId = generateLogEntryId(cacheKey.getKeyHash());
ByteBuf msg = encode(new LocalCachedMapInvalidate(instanceId, cacheKey.getKeyHash()));
String name = getLocalRawName(key);
return new CompletableFutureWrapper<>(
(CompletableFuture) commandExecutor.evalWriteAsync(getRawName(key), LongCodec.INSTANCE, RedisCommands.EVAL_BOOLEAN,
//"if redis.call('hget', KEYS[1], ARGV[1]) == ARGV[2] then "
"if ARGV[3] == '1' then "
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
+ "if ARGV[3] == '2' then "
+ "redis.call('zadd', KEYS[3], ARGV[5], ARGV[6]);"
+ "redis.call('publish', KEYS[2], ARGV[4]); "
+ "end;"
//+ "return redis.call('hdel', KEYS[1], ARGV[1]) "
//+ "else "
//+ "return 0 "
+ "return 1;"
, Arrays.asList(name, listener.getInvalidationTopicName(), listener.getUpdatesLogName()),
keyState, valueState, invalidateEntryOnChange, msg, System.currentTimeMillis(), entryId)
.thenCompose(s -> super.removeOperationAsync(key, value)));
}
@Override
public RFuture removeAsync(Object key, Object value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
if (cacheRemove(cacheKey, key, value)) {
broadcastLocalCacheStore((V) value, mapKey, cacheKey);
return new CompletableFutureWrapper<>(true);
} else {
mapKey.release();
return new CompletableFutureWrapper<>(false);
}
}
RFuture future = super.removeAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cache.remove(cacheKey);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture putIfExistsAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cachePutIfExists(cacheKey, key, value);
if (prevValue != null) {
broadcastLocalCacheStore((V) value, mapKey, cacheKey);
return new CompletableFutureWrapper<>((V) prevValue.getValue());
} else {
mapKey.release();
return new CompletableFutureWrapper((Void) null);
}
}
RFuture future = super.putIfExistsAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res != null) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public RFuture putIfAbsentAsync(K key, V value) {
if (storeMode == LocalCachedMapOptions.StoreMode.LOCALCACHE) {
ByteBuf mapKey = encodeMapKey(key);
CacheKey cacheKey = localCacheView.toCacheKey(mapKey);
CacheValue prevValue = cachePutIfAbsent(cacheKey, key, value);
if (prevValue == null) {
broadcastLocalCacheStore((V) value, mapKey, cacheKey);
return new CompletableFutureWrapper((Void) null);
} else {
mapKey.release();
return new CompletableFutureWrapper<>((V) prevValue.getValue());
}
}
RFuture future = super.putIfAbsentAsync(key, value);
CompletionStage f = future.thenApply(res -> {
if (res == null) {
CacheKey cacheKey = localCacheView.toCacheKey(key);
cachePut(cacheKey, key, value);
}
return res;
});
return new CompletableFutureWrapper<>(f);
}
@Override
public ByteBuf encode(Object value) {
try {
return LocalCachedMessageCodec.INSTANCE.getValueEncoder().encode(value);
} catch (IOException e) {
throw new IllegalArgumentException(e);
}
}
@Override
public Set cachedKeySet() {
return localCacheView.cachedKeySet();
}
@Override
public Collection cachedValues() {
return localCacheView.cachedValues();
}
@Override
public Set> cachedEntrySet() {
return localCacheView.cachedEntrySet();
}
@Override
public Map getCachedMap() {
return localCacheView.getCachedMap();
}
private String getLocalRawName(Object o) {
return getLocalRawName();
}
private String getLocalRawName() {
return super.getRawName();
}
}