diff --git a/redisson/src/main/java/org/redisson/jcache/JCache.java b/redisson/src/main/java/org/redisson/jcache/JCache.java index 21a12180e..482a365c3 100644 --- a/redisson/src/main/java/org/redisson/jcache/JCache.java +++ b/redisson/src/main/java/org/redisson/jcache/JCache.java @@ -15,6 +15,9 @@ */ package org.redisson.jcache; +import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; +import java.lang.reflect.Proxy; import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; @@ -82,6 +85,8 @@ import io.netty.util.internal.PlatformDependent; */ public class JCache extends RedissonObject implements Cache { + private final boolean v2 = System.getProperty("org.jsr107.tck.management.agentId") == null; + private final JCacheManager cacheManager; private final JCacheConfiguration config; private final ConcurrentMap, Map> listeners = @@ -93,6 +98,13 @@ public class JCache extends RedissonObject implements Cache { private boolean closed; private boolean hasOwnRedisson; + private static final RLock DUMMY_LOCK = (RLock) Proxy.newProxyInstance(JCache.class.getClassLoader(), new Class[] {RLock.class}, new InvocationHandler() { + @Override + public Object invoke(Object proxy, Method method, Object[] args) throws Throwable { + return null; + } + }); + public JCache(JCacheManager cacheManager, Redisson redisson, String name, JCacheConfiguration config, boolean hasOwnRedisson) { super(redisson.getConfig().getCodec(), redisson.getCommandExecutor(), name); @@ -176,7 +188,12 @@ public class JCache extends RedissonObject implements Cache { long startTime = currentNanoTime(); RLock lock = getLockedLock(key); try { - V value = getValueLocked(key); + V value; + if (v2) { + value = getValue(key); + } else { + value = getValueLocked(key); + } if (value == null) { cacheManager.getStatBean(this).addMisses(1); if (config.isReadThrough()) { @@ -253,6 +270,29 @@ public class JCache extends RedissonObject implements Cache { private V getValue(K key) { Long accessTimeout = getAccessTimeout(); + if (accessTimeout == -1) { + V value = evalRead(getName(), codec, RedisCommands.EVAL_MAP_VALUE, + "local value = redis.call('hget', KEYS[1], ARGV[3]); " + + "if value == false then " + + "return nil; " + + "end; " + + + "local expireDate = 92233720368547758; " + + "local expireDateScore = redis.call('zscore', KEYS[2], ARGV[3]); " + + "if expireDateScore ~= false then " + + "expireDate = tonumber(expireDateScore); " + + "end; " + + + "if expireDate <= tonumber(ARGV[2]) then " + + "return nil; " + + "end; " + + + "return value; ", + Arrays.asList(getName(), getTimeoutSetName(), getRemovedChannelName()), + accessTimeout, System.currentTimeMillis(), encodeMapKey(key)); + return value; + } + V value = evalWrite(getName(), codec, RedisCommands.EVAL_MAP_VALUE, "local value = redis.call('hget', KEYS[1], ARGV[3]); " + "if value == false then " @@ -301,7 +341,12 @@ public class JCache extends RedissonObject implements Cache { V load(K key) { RLock lock = getLockedLock(key); try { - V value = getValueLocked(key); + V value; + if (v2) { + value = getValue(key); + } else { + value = getValueLocked(key); + } if (value == null) { value = loadValue(key); } @@ -320,7 +365,11 @@ public class JCache extends RedissonObject implements Cache { } if (value != null) { long startTime = currentNanoTime(); - putValueLocked(key, value); + if (v2) { + putValue(key, value); + } else { + putValueLocked(key, value); + } cacheManager.getStatBean(this).addGetTime(currentNanoTime() - startTime); } return value; @@ -518,14 +567,15 @@ public class JCache extends RedissonObject implements Cache { private boolean putIfAbsentValue(K key, Object value) { Long creationTimeout = getCreationTimeout(); + if (creationTimeout == 0) { + return false; + } return evalWrite(getName(), codec, RedisCommands.EVAL_BOOLEAN, "if redis.call('hexists', KEYS[1], ARGV[2]) == 1 then " + "return 0; " + "else " - + "if ARGV[1] == '0' then " - + "return 0;" - + "elseif ARGV[1] ~= '-1' then " + + "if ARGV[1] ~= '-1' then " + "redis.call('hset', KEYS[1], ARGV[2], ARGV[3]); " + "redis.call('zadd', KEYS[2], ARGV[1], ARGV[2]); " + "local msg = struct.pack('Lc0Lc0', string.len(ARGV[2]), ARGV[2], string.len(ARGV[3]), ARGV[3]); " @@ -548,10 +598,11 @@ public class JCache extends RedissonObject implements Cache { } Long creationTimeout = getCreationTimeout(); + if (creationTimeout == 0) { + return false; + } return evalWrite(getName(), codec, RedisCommands.EVAL_BOOLEAN, - "if ARGV[1] == '0' then " - + "return 0;" - + "elseif ARGV[1] ~= '-1' then " + "if ARGV[1] ~= '-1' then " + "redis.call('hset', KEYS[1], ARGV[2], ARGV[3]); " + "redis.call('zadd', KEYS[2], ARGV[1], ARGV[2]); " + "local msg = struct.pack('Lc0Lc0', string.len(ARGV[2]), ARGV[2], string.len(ARGV[3]), ARGV[3]); " @@ -590,15 +641,18 @@ public class JCache extends RedissonObject implements Cache { } long startTime = currentNanoTime(); - boolean exists = false; - for (K key : keys) { - if (containsKey(key)) { - exists = true; + if (!config.isReadThrough()) { + boolean exists = false; + for (K key : keys) { + if (containsKey(key)) { + exists = true; + break; + } + } + if (!exists) { + cacheManager.getStatBean(this).addGetTime(currentNanoTime() - startTime); + return Collections.emptyMap(); } - } - if (!exists && !config.isReadThrough()) { - cacheManager.getStatBean(this).addGetTime(currentNanoTime() - startTime); - return Collections.emptyMap(); } @@ -608,43 +662,75 @@ public class JCache extends RedissonObject implements Cache { args.add(accessTimeout); args.add(System.currentTimeMillis()); encode(args, keys); + + Map res; + if (accessTimeout == -1) { + res = evalRead(getName(), codec, new RedisCommand>("EVAL", new MapGetAllDecoder(new ArrayList(keys), 0, true), ValueType.MAP_VALUE), + "local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores');" + + "local accessTimeout = ARGV[1]; " + + "local currentTime = tonumber(ARGV[2]); " + + "local hasExpire = #expireHead == 2 and tonumber(expireHead[2]) <= currentTime; " + + "local map = redis.call('hmget', KEYS[1], unpack(ARGV, 3, #ARGV)); " + + "local result = {};" + + "for i, value in ipairs(map) do " + + "if value ~= false then " + + "local key = ARGV[i+2]; " + + + "if hasExpire then " + + "local expireDate = 92233720368547758; " + + "local expireDateScore = redis.call('zscore', KEYS[2], key); " + + "if expireDateScore ~= false then " + + "expireDate = tonumber(expireDateScore); " + + "end; " + + "if expireDate <= currentTime then " + + "value = false; " + + "end; " + + "end; " + + "end; " - Map res = evalWrite(getName(), codec, new RedisCommand>("EVAL", new MapGetAllDecoder(new ArrayList(keys), 0, true), ValueType.MAP_VALUE), - "local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores');" - + "local accessTimeout = ARGV[1]; " - + "local currentTime = tonumber(ARGV[2]); " - + "local hasExpire = #expireHead == 2 and tonumber(expireHead[2]) <= currentTime; " - + "local map = redis.call('hmget', KEYS[1], unpack(ARGV, 3, #ARGV)); " - + "local result = {};" - + "for i, value in ipairs(map) do " - + "if value ~= false then " - + "local key = ARGV[i+2]; " - - + "if hasExpire then " - + "local expireDate = 92233720368547758; " - + "local expireDateScore = redis.call('zscore', KEYS[2], key); " - + "if expireDateScore ~= false then " - + "expireDate = tonumber(expireDateScore); " + + "table.insert(result, value); " + + "end; " + + "return result;", + Arrays.asList(getName(), getTimeoutSetName(), getRemovedChannelName()), args.toArray()); + } else { + res = evalWrite(getName(), codec, new RedisCommand>("EVAL", new MapGetAllDecoder(new ArrayList(keys), 0, true), ValueType.MAP_VALUE), + "local expireHead = redis.call('zrange', KEYS[2], 0, 0, 'withscores');" + + "local accessTimeout = ARGV[1]; " + + "local currentTime = tonumber(ARGV[2]); " + + "local hasExpire = #expireHead == 2 and tonumber(expireHead[2]) <= currentTime; " + + "local map = redis.call('hmget', KEYS[1], unpack(ARGV, 3, #ARGV)); " + + "local result = {};" + + "for i, value in ipairs(map) do " + + "if value ~= false then " + + "local key = ARGV[i+2]; " + + + "if hasExpire then " + + "local expireDate = 92233720368547758; " + + "local expireDateScore = redis.call('zscore', KEYS[2], key); " + + "if expireDateScore ~= false then " + + "expireDate = tonumber(expireDateScore); " + + "end; " + + "if expireDate <= currentTime then " + + "value = false; " + + "end; " + "end; " - + "if expireDate <= currentTime then " - + "value = false; " + + + "if accessTimeout == '0' then " + + "redis.call('hdel', KEYS[1], key); " + + "redis.call('zrem', KEYS[2], key); " + + "local msg = struct.pack('Lc0Lc0', string.len(key), key, string.len(value), value); " + + "redis.call('publish', KEYS[3], {key, value}); " + + "elseif accessTimeout ~= '-1' then " + + "redis.call('zadd', KEYS[2], accessTimeout, key); " + "end; " + "end; " - - + "if accessTimeout == '0' then " - + "redis.call('hdel', KEYS[1], key); " - + "redis.call('zrem', KEYS[2], key); " - + "local msg = struct.pack('Lc0Lc0', string.len(key), key, string.len(value), value); " - + "redis.call('publish', KEYS[3], {key, value}); " - + "elseif accessTimeout ~= '-1' then " - + "redis.call('zadd', KEYS[2], accessTimeout, key); " - + "end; " + + + "table.insert(result, value); " + "end; " + + "return result;", + Arrays.asList(getName(), getTimeoutSetName(), getRemovedChannelName()), args.toArray()); + } - + "table.insert(result, value); " - + "end; " - + "return result;", - Arrays.asList(getName(), getTimeoutSetName(), getRemovedChannelName()), args.toArray()); Map result = new HashMap(); for (Map.Entry entry : res.entrySet()) { @@ -674,7 +760,7 @@ public class JCache extends RedissonObject implements Cache { throw new NullPointerException(); } - return evalWrite(getName(), codec, RedisCommands.EVAL_BOOLEAN, + return evalRead(getName(), codec, RedisCommands.EVAL_BOOLEAN, "if redis.call('hexists', KEYS[1], ARGV[2]) == 0 then " + "return 0;" + "end;" @@ -729,7 +815,11 @@ public class JCache extends RedissonObject implements Cache { throw new CacheLoaderException(ex); } if (value != null) { - putValueLocked(key, value); + if (v2) { + putValue(key, value); + } else { + putValueLocked(key, value); + } } } } finally { @@ -751,6 +841,10 @@ public class JCache extends RedissonObject implements Cache { } private RLock getLockedLock(K key) { + if (v2) { + return DUMMY_LOCK; + } + String lockName = getLockName(key); RLock lock = redisson.getLock(lockName); try { @@ -776,7 +870,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - List result = getAndPutValueLocked(key, value); + List result; + if (v2) { + result = getAndPutValue(key, value); + } else { + result = getAndPutValueLocked(key, value); + } if (result.isEmpty()) { cacheManager.getStatBean(this).addPuts(1); cacheManager.getStatBean(this).addPutTime(currentNanoTime() - startTime); @@ -821,7 +920,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - boolean result = putValueLocked(key, value); + boolean result; + if (v2) { + result = putValue(key, value); + } else { + result = putValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addPuts(1); } @@ -988,7 +1092,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - List result = getAndPutValueLocked(key, value); + List result; + if (v2) { + result = getAndPutValue(key, value); + } else { + result = getAndPutValueLocked(key, value); + } if (result.isEmpty()) { cacheManager.getStatBean(this).addPuts(1); cacheManager.getStatBean(this).addMisses(1); @@ -1037,7 +1146,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - List result = getAndPutValueLocked(key, value); + List result; + if (v2) { + result = getAndPutValue(key, value); + } else { + result = getAndPutValueLocked(key, value); + } return getAndPutResult(startTime, result); } finally { lock.unlock(); @@ -1190,7 +1304,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - boolean result = putIfAbsentValueLocked(key, value); + boolean result; + if (v2) { + result = putIfAbsentValue(key, value); + } else { + result = putIfAbsentValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addPuts(1); try { @@ -1211,7 +1330,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - boolean result = putIfAbsentValueLocked(key, value); + boolean result; + if (v2) { + result = putIfAbsentValue(key, value); + } else { + result = putIfAbsentValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addPuts(1); } @@ -1271,8 +1395,7 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - V oldValue = getValue(key); - boolean result = removeValue(key); + V oldValue = getAndRemoveValue(key); try { cacheWriter.delete(key); } catch (CacheWriterException e) { @@ -1286,11 +1409,11 @@ public class JCache extends RedissonObject implements Cache { } throw new CacheWriterException(e); } - if (result) { + if (oldValue != null) { cacheManager.getStatBean(this).addRemovals(1); } cacheManager.getStatBean(this).addRemoveTime(currentNanoTime() - startTime); - return result; + return oldValue != null; } finally { lock.unlock(); } @@ -1412,7 +1535,11 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - result = removeValueLocked(key, value); + if (v2) { + result = removeValue(key, value); + } else { + result = removeValueLocked(key, value); + } if (result) { try { cacheWriter.delete(key); @@ -1438,7 +1565,11 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - result = removeValueLocked(key, value); + if (v2) { + result = removeValue(key, value); + } else { + result = removeValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addRemovals(1); @@ -1707,7 +1838,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - long result = replaceValueLocked(key, oldValue, newValue); + long result; + if (v2) { + result = replaceValue(key, oldValue, newValue); + } else { + result = replaceValueLocked(key, oldValue, newValue); + } if (result == 1) { try { cacheWriter.write(new JCacheEntry(key, newValue)); @@ -1739,7 +1875,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - long result = replaceValueLocked(key, oldValue, newValue); + long result; + if (v2) { + result = replaceValue(key, oldValue, newValue); + } else { + result = replaceValueLocked(key, oldValue, newValue); + } if (result == 1) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addPuts(1); @@ -1950,7 +2091,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - boolean result = replaceValueLocked(key, value); + boolean result; + if (v2) { + result = replaceValue(key, value); + } else { + result = replaceValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addPuts(1); @@ -1974,7 +2120,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - boolean result = replaceValueLocked(key, value); + boolean result; + if (v2) { + result = replaceValue(key, value); + } else { + result = replaceValueLocked(key, value); + } if (result) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addPuts(1); @@ -2003,7 +2154,12 @@ public class JCache extends RedissonObject implements Cache { if (config.isWriteThrough()) { RLock lock = getLockedLock(key); try { - V result = getAndReplaceValueLocked(key, value); + V result; + if (v2) { + result = getAndReplaceValue(key, value); + } else { + result = getAndReplaceValueLocked(key, value); + } if (result != null) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addPuts(1); @@ -2028,7 +2184,12 @@ public class JCache extends RedissonObject implements Cache { } else { RLock lock = getLockedLock(key); try { - V result = getAndReplaceValueLocked(key, value); + V result; + if (v2) { + result = getAndReplaceValue(key, value); + } else { + result = getAndReplaceValueLocked(key, value); + } if (result != null) { cacheManager.getStatBean(this).addHits(1); cacheManager.getStatBean(this).addPuts(1);