From f66697f29b0534e19e2b481813b6c0a4ce8368c1 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 25 Jan 2024 01:05:58 +0600 Subject: [PATCH 01/16] Support TTL in client side caching (using Caffeine library) --- pom.xml | 6 +++ .../redis/clients/jedis/ClientSideCache.java | 48 ++++++------------ .../redis/clients/jedis/UnifiedJedis.java | 4 +- .../redis/clients/jedis/util/CaffeineCSC.java | 50 +++++++++++++++++++ .../JedisClusterClientSideCacheTest.java | 9 ++-- .../jedis/JedisPooledClientSideCacheTest.java | 9 ++-- .../JedisSentineledClientSideCacheTest.java | 18 ++----- .../java/redis/clients/jedis/util/MapCSC.java | 39 +++++++++++++++ 8 files changed, 128 insertions(+), 55 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/util/CaffeineCSC.java create mode 100644 src/test/java/redis/clients/jedis/util/MapCSC.java diff --git a/pom.xml b/pom.xml index c9fd15d2cb..96a4e122f7 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,12 @@ gson 2.10.1 + + com.github.ben-manes.caffeine + caffeine + 2.9.3 + true + diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 62c5be28c2..482c9c0681 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -1,63 +1,47 @@ package redis.clients.jedis; import java.nio.ByteBuffer; -import java.util.HashMap; import java.util.List; -import java.util.Map; - import redis.clients.jedis.exceptions.JedisException; import redis.clients.jedis.util.SafeEncoder; -public class ClientSideCache { +public abstract class ClientSideCache { - private final Map cache; + protected ClientSideCache() { } - public ClientSideCache() { - this.cache = new HashMap<>(); - } + public abstract void clear(); - /** - * For testing purpose only. - * @param map - */ - ClientSideCache(Map map) { - this.cache = map; - } + protected abstract void remove(ByteBuffer key); - public final void clear() { - cache.clear(); - } + protected abstract void put(ByteBuffer key, Object value); + + protected abstract Object get(ByteBuffer key); - public final void invalidateKeys(List list) { + final void invalidateKeys(List list) { if (list == null) { clear(); - return; + } else { + list.forEach(this::invalidateKey); } - - list.forEach(this::invalidateKey); } private void invalidateKey(Object key) { if (key instanceof byte[]) { - cache.remove(convertKey((byte[]) key)); + remove(convertKey((byte[]) key)); } else { throw new JedisException("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); } } - protected void setKey(Object key, Object value) { - cache.put(getMapKey(key), value); - } - - protected T getValue(Object key) { - return (T) getMapValue(key); + final void set(Object key, Object value) { + put(makeKey(key), value); } - private Object getMapValue(Object key) { - return cache.get(getMapKey(key)); + final T get(Object key) { + return (T) get(makeKey(key)); } - private ByteBuffer getMapKey(Object key) { + private ByteBuffer makeKey(Object key) { if (key instanceof byte[]) { return convertKey((byte[]) key); } else { diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index ba7b36b134..343b24c842 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -750,11 +750,11 @@ public String set(String key, String value, SetParams params) { @Override public String get(String key) { if (clientSideCache != null) { - String cachedValue = clientSideCache.getValue(key); + String cachedValue = clientSideCache.get(key); if (cachedValue != null) return cachedValue; String value = executeCommand(commandObjects.get(key)); - if (value != null) clientSideCache.setKey(key, value); + if (value != null) clientSideCache.set(key, value); return value; } return executeCommand(commandObjects.get(key)); diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java new file mode 100644 index 0000000000..7a205f40ab --- /dev/null +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -0,0 +1,50 @@ +package redis.clients.jedis.util; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; +import redis.clients.jedis.ClientSideCache; + +public class CaffeineCSC extends ClientSideCache { + + private static final int DEFAULT_MAXIMUM_SIZE = 10_000; + + private final Cache cache; + + public CaffeineCSC() { + this(DEFAULT_MAXIMUM_SIZE); + } + + public CaffeineCSC(int maximumSize) { + this(Caffeine.newBuilder().maximumSize(maximumSize).build()); + } + + public CaffeineCSC(int maximumSize, int ttlSeconds) { + this(Caffeine.newBuilder().maximumSize(maximumSize).expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); + } + + public CaffeineCSC(Cache caffeineCache) { + this.cache = caffeineCache; + } + + @Override + public final void clear() { + cache.invalidateAll(); + } + + @Override + protected void remove(ByteBuffer key) { + cache.invalidate(key); + } + + @Override + protected void put(ByteBuffer key, Object value) { + cache.put(key, value); + } + + @Override + protected Object get(ByteBuffer key) { + return cache.getIfPresent(key); + } +} diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java index 3c8bc18c5c..8e276d9665 100644 --- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java @@ -14,6 +14,7 @@ import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.hamcrest.Matchers; import org.junit.Test; +import redis.clients.jedis.util.MapCSC; public class JedisClusterClientSideCacheTest extends JedisClusterTestBase { @@ -31,7 +32,7 @@ public class JedisClusterClientSideCacheTest extends JedisClusterTestBase { @Test public void simple() { - try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache())) { + try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC())) { jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.del("foo"); @@ -42,7 +43,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) { + try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); @@ -60,7 +61,7 @@ public void simpleWithSimpleMap() { @Test public void flushAll() { - try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache())) { + try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC())) { jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.flushAll(); @@ -71,7 +72,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) { + try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java index ad4313a4b7..805d9738d7 100644 --- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java @@ -12,6 +12,7 @@ import org.junit.After; import org.junit.Before; import org.junit.Test; +import redis.clients.jedis.util.MapCSC; public class JedisPooledClientSideCacheTest { @@ -42,7 +43,7 @@ public void tearDown() throws Exception { @Test public void simple() { - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache())) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC())) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.del("foo"); @@ -53,7 +54,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); @@ -71,7 +72,7 @@ public void simpleWithSimpleMap() { @Test public void flushAll() { - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache())) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC())) { control.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); control.flushAll(); @@ -82,7 +83,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new ClientSideCache(map), singleConnectionPoolConfig.get())) { + try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java index 9af243ffc7..5fa5a36f4b 100644 --- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java @@ -8,12 +8,11 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Set; -import java.util.function.Supplier; import java.util.stream.Collectors; -import org.apache.commons.pool2.impl.GenericObjectPoolConfig; import org.hamcrest.Matchers; import org.junit.Test; +import redis.clients.jedis.util.MapCSC; public class JedisSentineledClientSideCacheTest { @@ -28,16 +27,9 @@ public class JedisSentineledClientSideCacheTest { private static final JedisClientConfig sentinelClientConfig = DefaultJedisClientConfig.builder().resp3().build(); - private static final Supplier> singleConnectionPoolConfig - = () -> { - ConnectionPoolConfig poolConfig = new ConnectionPoolConfig(); - poolConfig.setMaxTotal(1); - return poolConfig; - }; - @Test public void simple() { - try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(), sentinels, sentinelClientConfig)) { + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.del("foo"); @@ -48,7 +40,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(map), sentinels, sentinelClientConfig)) { + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); @@ -66,7 +58,7 @@ public void simpleWithSimpleMap() { @Test public void flushAll() { - try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(), sentinels, sentinelClientConfig)) { + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertEquals("bar", jedis.get("foo")); jedis.flushAll(); @@ -77,7 +69,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { HashMap map = new HashMap<>(); - try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new ClientSideCache(map), sentinels, sentinelClientConfig)) { + try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); assertEquals("bar", jedis.get("foo")); diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java new file mode 100644 index 0000000000..a9d1ef6f37 --- /dev/null +++ b/src/test/java/redis/clients/jedis/util/MapCSC.java @@ -0,0 +1,39 @@ +package redis.clients.jedis.util; + +import java.nio.ByteBuffer; +import java.util.HashMap; +import java.util.Map; +import redis.clients.jedis.ClientSideCache; + +public class MapCSC extends ClientSideCache { + + private final Map cache; + + public MapCSC() { + this(new HashMap<>()); + } + + public MapCSC(Map map) { + this.cache = map; + } + + @Override + public final void clear() { + cache.clear(); + } + + @Override + protected void remove(ByteBuffer key) { + cache.remove(key); + } + + @Override + protected void put(ByteBuffer key, Object value) { + cache.put(key, value); + } + + @Override + protected Object get(ByteBuffer key) { + return cache.get(key); + } +} From 322ffeb8a876ec1fabfe40145fc1cb32c94f863e Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 25 Jan 2024 19:34:08 +0600 Subject: [PATCH 02/16] Also Guava cache --- pom.xml | 12 ++++- .../redis/clients/jedis/util/CaffeineCSC.java | 3 +- .../redis/clients/jedis/util/GuavaCSC.java | 51 +++++++++++++++++++ 3 files changed, 64 insertions(+), 2 deletions(-) create mode 100644 src/main/java/redis/clients/jedis/util/GuavaCSC.java diff --git a/pom.xml b/pom.xml index 96a4e122f7..c8c8d8149d 100644 --- a/pom.xml +++ b/pom.xml @@ -74,6 +74,15 @@ gson 2.10.1 + + + + + com.google.guava + guava + 33.0.0-jre + true + com.github.ben-manes.caffeine caffeine @@ -96,7 +105,8 @@ 1.19.0 test - + + junit junit diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index 7a205f40ab..d5537cc73b 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -21,7 +21,8 @@ public CaffeineCSC(int maximumSize) { } public CaffeineCSC(int maximumSize, int ttlSeconds) { - this(Caffeine.newBuilder().maximumSize(maximumSize).expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); + this(Caffeine.newBuilder().maximumSize(maximumSize) + .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); } public CaffeineCSC(Cache caffeineCache) { diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java new file mode 100644 index 0000000000..b4e31caa62 --- /dev/null +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -0,0 +1,51 @@ +package redis.clients.jedis.util; + +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import java.nio.ByteBuffer; +import java.util.concurrent.TimeUnit; +import redis.clients.jedis.ClientSideCache; + +public class GuavaCSC extends ClientSideCache { + + private static final int DEFAULT_MAXIMUM_SIZE = 10_000; + + private final Cache cache; + + public GuavaCSC() { + this(DEFAULT_MAXIMUM_SIZE); + } + + public GuavaCSC(int maximumSize) { + this(CacheBuilder.newBuilder().maximumSize(maximumSize).build()); + } + + public GuavaCSC(int maximumSize, int ttlSeconds) { + this(CacheBuilder.newBuilder().maximumSize(maximumSize) + .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); + } + + public GuavaCSC(Cache caffeineCache) { + this.cache = caffeineCache; + } + + @Override + public final void clear() { + cache.invalidateAll(); + } + + @Override + protected void remove(ByteBuffer key) { + cache.invalidate(key); + } + + @Override + protected void put(ByteBuffer key, Object value) { + cache.put(key, value); + } + + @Override + protected Object get(ByteBuffer key) { + return cache.getIfPresent(key); + } +} From 2ef437622c218088dcb0bc66e677714dd1544925 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 25 Jan 2024 20:29:05 +0600 Subject: [PATCH 03/16] format pom.xml --- pom.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pom.xml b/pom.xml index c8c8d8149d..1fcb758640 100644 --- a/pom.xml +++ b/pom.xml @@ -106,7 +106,7 @@ test - + junit junit From 9f160e2192a1e6eb5e8df701b11f58f7483cd94c Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 28 Jan 2024 13:58:10 +0600 Subject: [PATCH 04/16] Client-side caching by command arguments TODO: Compute hash code. --- .../redis/clients/jedis/ClientSideCache.java | 103 +++++++++++++----- .../clients/jedis/JedisClusterInfoCache.java | 2 +- .../redis/clients/jedis/UnifiedJedis.java | 18 +-- .../SentineledConnectionProvider.java | 2 +- .../redis/clients/jedis/util/CaffeineCSC.java | 19 ++-- .../redis/clients/jedis/util/GuavaCSC.java | 21 ++-- .../JedisClusterClientSideCacheTest.java | 4 +- .../jedis/JedisPooledClientSideCacheTest.java | 4 +- .../JedisSentineledClientSideCacheTest.java | 4 +- .../java/redis/clients/jedis/util/MapCSC.java | 23 ++-- 10 files changed, 125 insertions(+), 75 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 482c9c0681..063087cff5 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -1,55 +1,108 @@ package redis.clients.jedis; import java.nio.ByteBuffer; +import java.util.Collections; +import java.util.HashSet; import java.util.List; -import redis.clients.jedis.exceptions.JedisException; +import java.util.Map; +import java.util.Set; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.locks.Lock; +import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.function.Function; import redis.clients.jedis.util.SafeEncoder; public abstract class ClientSideCache { - protected ClientSideCache() { } + private final Map> keyHashes; + private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); + private final Lock readLock = rwl.readLock(); + private final Lock writeLock = rwl.writeLock(); - public abstract void clear(); + protected ClientSideCache() { + this.keyHashes = new ConcurrentHashMap<>(); + } + + protected ClientSideCache(Map> keyHashes) { + this.keyHashes = keyHashes; + } + + public abstract void invalidateAll(); - protected abstract void remove(ByteBuffer key); + protected abstract void invalidateAll(Iterable hashes); - protected abstract void put(ByteBuffer key, Object value); + protected abstract void put(long hash, Object value); - protected abstract Object get(ByteBuffer key); + protected abstract Object get(long hash); final void invalidateKeys(List list) { if (list == null) { - clear(); - } else { - list.forEach(this::invalidateKey); + invalidateAll(); + return; } + + Set hashes = new HashSet<>(); + list.forEach(key -> hashes.addAll(getHashes(key))); + invalidateAll(hashes); } - private void invalidateKey(Object key) { - if (key instanceof byte[]) { - remove(convertKey((byte[]) key)); - } else { - throw new JedisException("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); + private Set getHashes(Object key) { + if (!(key instanceof byte[])) { + throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); + } + + final ByteBuffer mapKey = makeKey((byte[]) key); + readLock.lock(); + try { + Set hashes = keyHashes.get(mapKey); + return hashes != null ? hashes : Collections.emptySet(); + } finally { + readLock.unlock(); } } - final void set(Object key, Object value) { - put(makeKey(key), value); + final T getValue(Function, T> loader, CommandObject command, String... keys) { + + final long hash = getHash(command); + + T value = (T) get(hash); + if (value != null) { + return value; + } + + value = loader.apply(command); + if (value != null) { + writeLock.lock(); + try { + put(hash, value); + for (String key : keys) { + ByteBuffer mapKey = makeKey(key); + if (keyHashes.containsKey(mapKey)) { + keyHashes.get(mapKey).add(hash); + } else { + Set set = new HashSet<>(); + set.add(hash); + keyHashes.put(mapKey, set); + } + } + } finally { + writeLock.unlock(); + } + } + + return value; } - final T get(Object key) { - return (T) get(makeKey(key)); + private long getHash(CommandObject command) { + // TODO: + return 0; } - private ByteBuffer makeKey(Object key) { - if (key instanceof byte[]) { - return convertKey((byte[]) key); - } else { - return convertKey(SafeEncoder.encode(String.valueOf(key))); - } + private ByteBuffer makeKey(String key) { + return makeKey(SafeEncoder.encode(key)); } - private static ByteBuffer convertKey(byte[] b) { + private static ByteBuffer makeKey(byte[] b) { return ByteBuffer.wrap(b); } } diff --git a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java index 5646dbfb59..9402b150ba 100644 --- a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java +++ b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java @@ -227,7 +227,7 @@ private void discoverClusterSlots(Connection jedis) { Arrays.fill(slots, null); Arrays.fill(slotNodes, null); if (clientSideCache != null) { - clientSideCache.clear(); + clientSideCache.invalidateAll(); } Set hostAndPortKeys = new HashSet<>(); diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index 343b24c842..c7936bfb62 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -295,6 +295,14 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig); } + private T executeClientSideCacheCommand(CommandObject command) { + if (clientSideCache == null) { + return executeCommand(command); + } + + return clientSideCache.getValue((cmd) -> executeCommand(cmd), command); + } + public String ping() { return checkAndBroadcastCommand(commandObjects.ping()); } @@ -749,15 +757,7 @@ public String set(String key, String value, SetParams params) { @Override public String get(String key) { - if (clientSideCache != null) { - String cachedValue = clientSideCache.get(key); - if (cachedValue != null) return cachedValue; - - String value = executeCommand(commandObjects.get(key)); - if (value != null) clientSideCache.set(key, value); - return value; - } - return executeCommand(commandObjects.get(key)); + return executeClientSideCacheCommand(commandObjects.get(key)); } @Override diff --git a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java index e335803b62..ae883e2af3 100644 --- a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java @@ -128,7 +128,7 @@ private void initMaster(HostAndPort master) { pool = newPool; LOG.info("Created connection pool to master at {}.", master); if (clientSideCache != null) { - clientSideCache.clear(); + clientSideCache.invalidateAll(); } if (existingPool != null) { diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index d5537cc73b..c3364168c7 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -2,7 +2,6 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import redis.clients.jedis.ClientSideCache; @@ -10,7 +9,7 @@ public class CaffeineCSC extends ClientSideCache { private static final int DEFAULT_MAXIMUM_SIZE = 10_000; - private final Cache cache; + private final Cache cache; public CaffeineCSC() { this(DEFAULT_MAXIMUM_SIZE); @@ -25,27 +24,27 @@ public CaffeineCSC(int maximumSize, int ttlSeconds) { .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); } - public CaffeineCSC(Cache caffeineCache) { + public CaffeineCSC(Cache caffeineCache) { this.cache = caffeineCache; } @Override - public final void clear() { + public final void invalidateAll() { cache.invalidateAll(); } @Override - protected void remove(ByteBuffer key) { - cache.invalidate(key); + protected void invalidateAll(Iterable hashes) { + cache.invalidateAll(hashes); } @Override - protected void put(ByteBuffer key, Object value) { - cache.put(key, value); + protected void put(long hash, Object value) { + cache.put(hash, value); } @Override - protected Object get(ByteBuffer key) { - return cache.getIfPresent(key); + protected Object get(long hash) { + return cache.getIfPresent(hash); } } diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java index b4e31caa62..e51e0c25f8 100644 --- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -2,7 +2,6 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; -import java.nio.ByteBuffer; import java.util.concurrent.TimeUnit; import redis.clients.jedis.ClientSideCache; @@ -10,7 +9,7 @@ public class GuavaCSC extends ClientSideCache { private static final int DEFAULT_MAXIMUM_SIZE = 10_000; - private final Cache cache; + private final Cache cache; public GuavaCSC() { this(DEFAULT_MAXIMUM_SIZE); @@ -25,27 +24,27 @@ public GuavaCSC(int maximumSize, int ttlSeconds) { .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); } - public GuavaCSC(Cache caffeineCache) { - this.cache = caffeineCache; + public GuavaCSC(Cache guavaCache) { + this.cache = guavaCache; } @Override - public final void clear() { + public final void invalidateAll() { cache.invalidateAll(); } @Override - protected void remove(ByteBuffer key) { - cache.invalidate(key); + protected void invalidateAll(Iterable hashes) { + cache.invalidateAll(hashes); } @Override - protected void put(ByteBuffer key, Object value) { - cache.put(key, value); + protected void put(long hash, Object value) { + cache.put(hash, value); } @Override - protected Object get(ByteBuffer key) { - return cache.getIfPresent(key); + protected Object get(long hash) { + return cache.getIfPresent(hash); } } diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java index 8e276d9665..2f11af837b 100644 --- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java @@ -42,7 +42,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); @@ -71,7 +71,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisCluster jedis = new JedisCluster(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java index 805d9738d7..b5741454db 100644 --- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java @@ -53,7 +53,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); @@ -82,7 +82,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisPooled jedis = new JedisPooled(hnp, clientConfig.get(), new MapCSC(map), singleConnectionPoolConfig.get())) { control.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java index 5fa5a36f4b..de20a356f9 100644 --- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java @@ -39,7 +39,7 @@ public void simple() { @Test public void simpleWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); @@ -68,7 +68,7 @@ public void flushAll() { @Test public void flushAllWithSimpleMap() { - HashMap map = new HashMap<>(); + HashMap map = new HashMap<>(); try (JedisSentineled jedis = new JedisSentineled(MASTER_NAME, masterClientConfig, new MapCSC(map), sentinels, sentinelClientConfig)) { jedis.set("foo", "bar"); assertThat(map, Matchers.aMapWithSize(0)); diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java index a9d1ef6f37..1db1a64810 100644 --- a/src/test/java/redis/clients/jedis/util/MapCSC.java +++ b/src/test/java/redis/clients/jedis/util/MapCSC.java @@ -1,39 +1,38 @@ package redis.clients.jedis.util; -import java.nio.ByteBuffer; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import redis.clients.jedis.ClientSideCache; public class MapCSC extends ClientSideCache { - private final Map cache; + private final Map cache; public MapCSC() { - this(new HashMap<>()); + this(new ConcurrentHashMap<>()); } - public MapCSC(Map map) { + public MapCSC(Map map) { this.cache = map; } @Override - public final void clear() { + public final void invalidateAll() { cache.clear(); } @Override - protected void remove(ByteBuffer key) { - cache.remove(key); + protected void invalidateAll(Iterable hashes) { + hashes.forEach(hash -> cache.remove(hash)); } @Override - protected void put(ByteBuffer key, Object value) { - cache.put(key, value); + protected void put(long hash, Object value) { + cache.put(hash, value); } @Override - protected Object get(ByteBuffer key) { - return cache.get(key); + protected Object get(long hash) { + return cache.get(hash); } } From 3827e7d7dc98480d28f0e1b67559d288a94bf31a Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Sun, 28 Jan 2024 16:08:10 +0600 Subject: [PATCH 05/16] send keys --- src/main/java/redis/clients/jedis/UnifiedJedis.java | 6 +++--- .../clients/jedis/JedisClusterClientSideCacheTest.java | 1 - .../redis/clients/jedis/JedisPooledClientSideCacheTest.java | 1 - .../clients/jedis/JedisSentineledClientSideCacheTest.java | 1 - 4 files changed, 3 insertions(+), 6 deletions(-) diff --git a/src/main/java/redis/clients/jedis/UnifiedJedis.java b/src/main/java/redis/clients/jedis/UnifiedJedis.java index c7936bfb62..3a2dec9d77 100644 --- a/src/main/java/redis/clients/jedis/UnifiedJedis.java +++ b/src/main/java/redis/clients/jedis/UnifiedJedis.java @@ -295,12 +295,12 @@ public void setBroadcastAndRoundRobinConfig(JedisBroadcastAndRoundRobinConfig co this.commandObjects.setBroadcastAndRoundRobinConfig(this.broadcastAndRoundRobinConfig); } - private T executeClientSideCacheCommand(CommandObject command) { + private T executeClientSideCacheCommand(CommandObject command, String... keys) { if (clientSideCache == null) { return executeCommand(command); } - return clientSideCache.getValue((cmd) -> executeCommand(cmd), command); + return clientSideCache.getValue((cmd) -> executeCommand(cmd), command, keys); } public String ping() { @@ -757,7 +757,7 @@ public String set(String key, String value, SetParams params) { @Override public String get(String key) { - return executeClientSideCacheCommand(commandObjects.get(key)); + return executeClientSideCacheCommand(commandObjects.get(key), key); } @Override diff --git a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java index 2f11af837b..60ddf002d7 100644 --- a/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisClusterClientSideCacheTest.java @@ -4,7 +4,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.Set; diff --git a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java index b5741454db..2e641e0f3a 100644 --- a/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisPooledClientSideCacheTest.java @@ -4,7 +4,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import java.nio.ByteBuffer; import java.util.HashMap; import java.util.function.Supplier; import org.apache.commons.pool2.impl.GenericObjectPoolConfig; diff --git a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java index de20a356f9..9e5f720933 100644 --- a/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java +++ b/src/test/java/redis/clients/jedis/JedisSentineledClientSideCacheTest.java @@ -4,7 +4,6 @@ import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNull; -import java.nio.ByteBuffer; import java.util.Arrays; import java.util.HashMap; import java.util.Set; From e910168f2cbdef84b20abb18daa5056f607e5b52 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:20:30 +0600 Subject: [PATCH 06/16] todo comment for clean-up --- src/main/java/redis/clients/jedis/ClientSideCache.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 063087cff5..d21170afe3 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -14,7 +14,7 @@ public abstract class ClientSideCache { - private final Map> keyHashes; + private final Map> keyHashes; // TODO: clean-up private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); private final Lock readLock = rwl.readLock(); private final Lock writeLock = rwl.writeLock(); @@ -44,6 +44,7 @@ final void invalidateKeys(List list) { Set hashes = new HashSet<>(); list.forEach(key -> hashes.addAll(getHashes(key))); invalidateAll(hashes); + // TODO: clean-up keyHashes } private Set getHashes(Object key) { From 0ba4d7d3f0654c330f76140545062e31780bd8bb Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 30 Jan 2024 16:24:16 +0600 Subject: [PATCH 07/16] rename method to invalidate --- src/main/java/redis/clients/jedis/ClientSideCache.java | 2 +- src/main/java/redis/clients/jedis/Protocol.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index d21170afe3..616fe7d7b5 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -35,7 +35,7 @@ protected ClientSideCache(Map> keyHashes) { protected abstract Object get(long hash); - final void invalidateKeys(List list) { + final void invalidate(List list) { if (list == null) { invalidateAll(); return; diff --git a/src/main/java/redis/clients/jedis/Protocol.java b/src/main/java/redis/clients/jedis/Protocol.java index 4af1261cd4..4bd82fec1e 100644 --- a/src/main/java/redis/clients/jedis/Protocol.java +++ b/src/main/java/redis/clients/jedis/Protocol.java @@ -248,7 +248,7 @@ private static void processPush(final RedisInputStream is, ClientSideCache cache //System.out.println("PUSH: " + SafeEncoder.encodeObject(list)); if (list.size() == 2 && list.get(0) instanceof byte[] && Arrays.equals(INVALIDATE_BYTES, (byte[]) list.get(0))) { - cache.invalidateKeys((List) list.get(1)); + cache.invalidate((List) list.get(1)); } } From e3a5900fa32f931373c02d421fa1e6f85762c0ce Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Wed, 31 Jan 2024 00:41:31 +0600 Subject: [PATCH 08/16] Client-side caching by hashing command arguments --- .../redis/clients/jedis/ClientSideCache.java | 17 ++-- .../redis/clients/jedis/util/CaffeineCSC.java | 12 +++ .../redis/clients/jedis/util/GuavaCSC.java | 82 +++++++++++++++---- .../java/redis/clients/jedis/util/MapCSC.java | 12 +++ 4 files changed, 97 insertions(+), 26 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 616fe7d7b5..2b15fb75df 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -23,18 +23,10 @@ protected ClientSideCache() { this.keyHashes = new ConcurrentHashMap<>(); } - protected ClientSideCache(Map> keyHashes) { - this.keyHashes = keyHashes; - } - public abstract void invalidateAll(); protected abstract void invalidateAll(Iterable hashes); - protected abstract void put(long hash, Object value); - - protected abstract Object get(long hash); - final void invalidate(List list) { if (list == null) { invalidateAll(); @@ -62,6 +54,10 @@ private Set getHashes(Object key) { } } + protected abstract void put(long hash, Object value); + + protected abstract Object get(long hash); + final T getValue(Function, T> loader, CommandObject command, String... keys) { final long hash = getHash(command); @@ -94,10 +90,7 @@ final T getValue(Function, T> loader, CommandObject comm return value; } - private long getHash(CommandObject command) { - // TODO: - return 0; - } + protected abstract long getHash(CommandObject command); private ByteBuffer makeKey(String key) { return makeKey(SafeEncoder.encode(key)); diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index c3364168c7..c12f7a475b 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -2,8 +2,11 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; +import java.util.Arrays; import java.util.concurrent.TimeUnit; import redis.clients.jedis.ClientSideCache; +import redis.clients.jedis.CommandObject; +import redis.clients.jedis.args.Rawable; public class CaffeineCSC extends ClientSideCache { @@ -47,4 +50,13 @@ protected void put(long hash, Object value) { protected Object get(long hash) { return cache.getIfPresent(hash); } + + @Override // TODO: + protected final long getHash(CommandObject command) { + long result = 1; + for (Rawable raw : command.getArguments()) { + result = 31 * result + Arrays.hashCode(raw.getRaw()); + } + return 31 * result + command.getBuilder().hashCode(); + } } diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java index e51e0c25f8..282c03790e 100644 --- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -2,30 +2,25 @@ import com.google.common.cache.Cache; import com.google.common.cache.CacheBuilder; +import com.google.common.hash.HashFunction; +import com.google.common.hash.Hasher; +import java.time.Duration; import java.util.concurrent.TimeUnit; import redis.clients.jedis.ClientSideCache; +import redis.clients.jedis.CommandObject; public class GuavaCSC extends ClientSideCache { private static final int DEFAULT_MAXIMUM_SIZE = 10_000; + private static final int DEFAULT_EXPIRE_MINUTES = 5; + private static final HashFunction DEFAULT_FUNCTION = com.google.common.hash.Hashing.fingerprint2011(); private final Cache cache; + private final HashFunction function; - public GuavaCSC() { - this(DEFAULT_MAXIMUM_SIZE); - } - - public GuavaCSC(int maximumSize) { - this(CacheBuilder.newBuilder().maximumSize(maximumSize).build()); - } - - public GuavaCSC(int maximumSize, int ttlSeconds) { - this(CacheBuilder.newBuilder().maximumSize(maximumSize) - .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); - } - - public GuavaCSC(Cache guavaCache) { + public GuavaCSC(Cache guavaCache, HashFunction hashFunction) { this.cache = guavaCache; + this.function = hashFunction; } @Override @@ -47,4 +42,63 @@ protected void put(long hash, Object value) { protected Object get(long hash) { return cache.getIfPresent(hash); } + + @Override + protected final long getHash(CommandObject command) { + Hasher hasher = function.newHasher(); + command.getArguments().forEach(raw -> hasher.putBytes(raw.getRaw())); + hasher.putInt(command.getBuilder().hashCode()); + return hasher.hash().asLong(); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private long maximumSize = DEFAULT_MAXIMUM_SIZE; + private Duration expireDuration = null; + private long expireTime = DEFAULT_EXPIRE_MINUTES; + private TimeUnit expireTimeUnit = TimeUnit.MINUTES; + + private HashFunction hashFunction = DEFAULT_FUNCTION; + + private Builder() { } + + public Builder maximumSize(int size) { + this.maximumSize = size; + return this; + } + + public Builder ttl(Duration duration) { + this.expireDuration = duration; + return this; + } + + public Builder ttl(long time, TimeUnit unit) { + this.expireTime = time; + this.expireTimeUnit = unit; + return this; + } + + public Builder hashFunction(HashFunction function) { + this.hashFunction = function; + return this; + } + + public GuavaCSC build() { + CacheBuilder cb = CacheBuilder.newBuilder(); + + cb.maximumSize(maximumSize); + + if (expireDuration != null) { + cb.expireAfterWrite(expireDuration); + } else { + cb.expireAfterWrite(expireTime, expireTimeUnit); + } + + return new GuavaCSC(cb.build(), hashFunction); + } + } } diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java index 1db1a64810..0915fd9050 100644 --- a/src/test/java/redis/clients/jedis/util/MapCSC.java +++ b/src/test/java/redis/clients/jedis/util/MapCSC.java @@ -1,8 +1,11 @@ package redis.clients.jedis.util; +import java.util.Arrays; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import redis.clients.jedis.ClientSideCache; +import redis.clients.jedis.CommandObject; +import redis.clients.jedis.args.Rawable; public class MapCSC extends ClientSideCache { @@ -35,4 +38,13 @@ protected void put(long hash, Object value) { protected Object get(long hash) { return cache.get(hash); } + + @Override + protected final long getHash(CommandObject command) { + long result = 1; + for (Rawable raw : command.getArguments()) { + result = 31 * result + Arrays.hashCode(raw.getRaw()); + } + return 31 * result + command.getBuilder().hashCode(); + } } From d7720a1386b9ad633925cda32eddcf848f39bc72 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 1 Feb 2024 00:47:01 +0600 Subject: [PATCH 09/16] Hash command arguments for CaffeineCSC using OpenHFT hashing --- pom.xml | 6 ++ .../redis/clients/jedis/util/CaffeineCSC.java | 71 ++++++++++++++----- .../redis/clients/jedis/util/GuavaCSC.java | 28 +++----- 3 files changed, 66 insertions(+), 39 deletions(-) diff --git a/pom.xml b/pom.xml index 1fcb758640..e6ff5bc70b 100644 --- a/pom.xml +++ b/pom.xml @@ -89,6 +89,12 @@ 2.9.3 true + + net.openhft + zero-allocation-hashing + 0.16 + true + diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index c12f7a475b..36f354bc4a 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -2,8 +2,8 @@ import com.github.benmanes.caffeine.cache.Cache; import com.github.benmanes.caffeine.cache.Caffeine; -import java.util.Arrays; import java.util.concurrent.TimeUnit; +import net.openhft.hashing.LongHashFunction; import redis.clients.jedis.ClientSideCache; import redis.clients.jedis.CommandObject; import redis.clients.jedis.args.Rawable; @@ -11,24 +11,15 @@ public class CaffeineCSC extends ClientSideCache { private static final int DEFAULT_MAXIMUM_SIZE = 10_000; + private static final int DEFAULT_EXPIRE_SECONDS = 100; + private static final LongHashFunction DEFAULT_HASH_FUNCTION = LongHashFunction.xx3(); private final Cache cache; + private final LongHashFunction function; - public CaffeineCSC() { - this(DEFAULT_MAXIMUM_SIZE); - } - - public CaffeineCSC(int maximumSize) { - this(Caffeine.newBuilder().maximumSize(maximumSize).build()); - } - - public CaffeineCSC(int maximumSize, int ttlSeconds) { - this(Caffeine.newBuilder().maximumSize(maximumSize) - .expireAfterWrite(ttlSeconds, TimeUnit.SECONDS).build()); - } - - public CaffeineCSC(Cache caffeineCache) { + public CaffeineCSC(Cache caffeineCache, LongHashFunction hashFunction) { this.cache = caffeineCache; + this.function = hashFunction; } @Override @@ -51,12 +42,54 @@ protected Object get(long hash) { return cache.getIfPresent(hash); } - @Override // TODO: + @Override protected final long getHash(CommandObject command) { - long result = 1; + long[] nums = new long[command.getArguments().size() + 1]; + int idx = 0; for (Rawable raw : command.getArguments()) { - result = 31 * result + Arrays.hashCode(raw.getRaw()); + nums[idx++] = function.hashBytes(raw.getRaw()); + } + nums[idx] = function.hashInt(command.getBuilder().hashCode()); + return function.hashLongs(nums); + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + + private long maximumSize = DEFAULT_MAXIMUM_SIZE; + private long expireTime = DEFAULT_EXPIRE_SECONDS; + private final TimeUnit expireTimeUnit = TimeUnit.SECONDS; + + private LongHashFunction hashFunction = DEFAULT_HASH_FUNCTION; + + private Builder() { } + + public Builder maximumSize(int size) { + this.maximumSize = size; + return this; + } + + public Builder ttl(int seconds) { + this.expireTime = seconds; + return this; + } + + public Builder hashFunction(LongHashFunction function) { + this.hashFunction = function; + return this; + } + + public CaffeineCSC build() { + Caffeine cb = Caffeine.newBuilder(); + + cb.maximumSize(maximumSize); + + cb.expireAfterWrite(expireTime, expireTimeUnit); + + return new CaffeineCSC(cb.build(), hashFunction); } - return 31 * result + command.getBuilder().hashCode(); } } diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java index 282c03790e..643c62b9a9 100644 --- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -4,7 +4,6 @@ import com.google.common.cache.CacheBuilder; import com.google.common.hash.HashFunction; import com.google.common.hash.Hasher; -import java.time.Duration; import java.util.concurrent.TimeUnit; import redis.clients.jedis.ClientSideCache; import redis.clients.jedis.CommandObject; @@ -12,8 +11,8 @@ public class GuavaCSC extends ClientSideCache { private static final int DEFAULT_MAXIMUM_SIZE = 10_000; - private static final int DEFAULT_EXPIRE_MINUTES = 5; - private static final HashFunction DEFAULT_FUNCTION = com.google.common.hash.Hashing.fingerprint2011(); + private static final int DEFAULT_EXPIRE_SECONDS = 100; + private static final HashFunction DEFAULT_HASH_FUNCTION = com.google.common.hash.Hashing.fingerprint2011(); private final Cache cache; private final HashFunction function; @@ -58,11 +57,10 @@ public static Builder builder() { public static class Builder { private long maximumSize = DEFAULT_MAXIMUM_SIZE; - private Duration expireDuration = null; - private long expireTime = DEFAULT_EXPIRE_MINUTES; - private TimeUnit expireTimeUnit = TimeUnit.MINUTES; + private long expireTime = DEFAULT_EXPIRE_SECONDS; + private final TimeUnit expireTimeUnit = TimeUnit.SECONDS; - private HashFunction hashFunction = DEFAULT_FUNCTION; + private HashFunction hashFunction = DEFAULT_HASH_FUNCTION; private Builder() { } @@ -71,14 +69,8 @@ public Builder maximumSize(int size) { return this; } - public Builder ttl(Duration duration) { - this.expireDuration = duration; - return this; - } - - public Builder ttl(long time, TimeUnit unit) { - this.expireTime = time; - this.expireTimeUnit = unit; + public Builder ttl(int seconds) { + this.expireTime = seconds; return this; } @@ -92,11 +84,7 @@ public GuavaCSC build() { cb.maximumSize(maximumSize); - if (expireDuration != null) { - cb.expireAfterWrite(expireDuration); - } else { - cb.expireAfterWrite(expireTime, expireTimeUnit); - } + cb.expireAfterWrite(expireTime, expireTimeUnit); return new GuavaCSC(cb.build(), hashFunction); } From d3acff22529e6469bb371cc909feaf3752df59e2 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Thu, 1 Feb 2024 15:02:39 +0600 Subject: [PATCH 10/16] Clean-up keyHashes map --- .../redis/clients/jedis/ClientSideCache.java | 33 +++++++++---------- 1 file changed, 15 insertions(+), 18 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 2b15fb75df..1371a2d376 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -1,23 +1,19 @@ package redis.clients.jedis; import java.nio.ByteBuffer; -import java.util.Collections; import java.util.HashSet; import java.util.List; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.Lock; -import java.util.concurrent.locks.ReentrantReadWriteLock; +import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import redis.clients.jedis.util.SafeEncoder; public abstract class ClientSideCache { - private final Map> keyHashes; // TODO: clean-up - private final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock(); - private final Lock readLock = rwl.readLock(); - private final Lock writeLock = rwl.writeLock(); + private final Map> keyHashes; + private final ReentrantLock writeLock = new ReentrantLock(); protected ClientSideCache() { this.keyHashes = new ConcurrentHashMap<>(); @@ -33,24 +29,25 @@ final void invalidate(List list) { return; } - Set hashes = new HashSet<>(); - list.forEach(key -> hashes.addAll(getHashes(key))); - invalidateAll(hashes); - // TODO: clean-up keyHashes + list.forEach(this::invalidate0); } - private Set getHashes(Object key) { + private void invalidate0(Object key) { if (!(key instanceof byte[])) { throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); } final ByteBuffer mapKey = makeKey((byte[]) key); - readLock.lock(); - try { - Set hashes = keyHashes.get(mapKey); - return hashes != null ? hashes : Collections.emptySet(); - } finally { - readLock.unlock(); + + Set hashes = keyHashes.get(mapKey); + if (hashes != null) { + writeLock.lock(); + try { + invalidateAll(hashes); + keyHashes.remove(mapKey); + } finally { + writeLock.unlock(); + } } } From 58e2f439205473d77a3e1f29171785d04be3d30c Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:33:49 +0600 Subject: [PATCH 11/16] added javadoc --- src/main/java/redis/clients/jedis/ClientSideCache.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 1371a2d376..f630e83ada 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -10,6 +10,11 @@ import java.util.function.Function; import redis.clients.jedis.util.SafeEncoder; +/** + * The class to manage the client-side caching. User can provide any of implementation of this class to the client + * object; e.g. {@link redis.clients.jedis.util.CaffeineCSC CaffeineCSC} or + * {@link redis.clients.jedis.util.GuavaCSC GuavaCSC} or a custom implementation of their own. + */ public abstract class ClientSideCache { private final Map> keyHashes; From dd45f5fd53b863af1c0710df9e0771f2a283fd14 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:35:08 +0600 Subject: [PATCH 12/16] rename method --- src/main/java/redis/clients/jedis/ClientSideCache.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index f630e83ada..598e853ffb 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -34,10 +34,10 @@ final void invalidate(List list) { return; } - list.forEach(this::invalidate0); + list.forEach(this::invalidateKeyAndRespectiveCommandHashes); } - private void invalidate0(Object key) { + private void invalidateKeyAndRespectiveCommandHashes(Object key) { if (!(key instanceof byte[])) { throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); } From ef69cb5d3b3f852fcb2b10e4aa68c994a693c978 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:36:21 +0600 Subject: [PATCH 13/16] remove lock --- .../redis/clients/jedis/ClientSideCache.java | 34 ++++++------------- 1 file changed, 11 insertions(+), 23 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 598e853ffb..b16babab2d 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -6,7 +6,6 @@ import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.locks.ReentrantLock; import java.util.function.Function; import redis.clients.jedis.util.SafeEncoder; @@ -18,7 +17,6 @@ public abstract class ClientSideCache { private final Map> keyHashes; - private final ReentrantLock writeLock = new ReentrantLock(); protected ClientSideCache() { this.keyHashes = new ConcurrentHashMap<>(); @@ -46,13 +44,8 @@ private void invalidateKeyAndRespectiveCommandHashes(Object key) { Set hashes = keyHashes.get(mapKey); if (hashes != null) { - writeLock.lock(); - try { - invalidateAll(hashes); - keyHashes.remove(mapKey); - } finally { - writeLock.unlock(); - } + invalidateAll(hashes); + keyHashes.remove(mapKey); } } @@ -71,21 +64,16 @@ final T getValue(Function, T> loader, CommandObject comm value = loader.apply(command); if (value != null) { - writeLock.lock(); - try { - put(hash, value); - for (String key : keys) { - ByteBuffer mapKey = makeKey(key); - if (keyHashes.containsKey(mapKey)) { - keyHashes.get(mapKey).add(hash); - } else { - Set set = new HashSet<>(); - set.add(hash); - keyHashes.put(mapKey, set); - } + put(hash, value); + for (String key : keys) { + ByteBuffer mapKey = makeKey(key); + if (keyHashes.containsKey(mapKey)) { + keyHashes.get(mapKey).add(hash); + } else { + Set set = new HashSet<>(); + set.add(hash); + keyHashes.put(mapKey, set); } - } finally { - writeLock.unlock(); } } From 4dd02a4e3bcf7102f5ea5ea212dc16f3938461e3 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:38:48 +0600 Subject: [PATCH 14/16] descriptive name --- .../redis/clients/jedis/ClientSideCache.java | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index b16babab2d..45db9d83e2 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -16,10 +16,10 @@ */ public abstract class ClientSideCache { - private final Map> keyHashes; + private final Map> keyToCommandHashes; protected ClientSideCache() { - this.keyHashes = new ConcurrentHashMap<>(); + this.keyToCommandHashes = new ConcurrentHashMap<>(); } public abstract void invalidateAll(); @@ -40,12 +40,12 @@ private void invalidateKeyAndRespectiveCommandHashes(Object key) { throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); } - final ByteBuffer mapKey = makeKey((byte[]) key); + final ByteBuffer mapKey = makeKeyForKeyToCommandHashes((byte[]) key); - Set hashes = keyHashes.get(mapKey); + Set hashes = keyToCommandHashes.get(mapKey); if (hashes != null) { invalidateAll(hashes); - keyHashes.remove(mapKey); + keyToCommandHashes.remove(mapKey); } } @@ -66,13 +66,13 @@ final T getValue(Function, T> loader, CommandObject comm if (value != null) { put(hash, value); for (String key : keys) { - ByteBuffer mapKey = makeKey(key); - if (keyHashes.containsKey(mapKey)) { - keyHashes.get(mapKey).add(hash); + ByteBuffer mapKey = makeKeyForKeyToCommandHashes(key); + if (keyToCommandHashes.containsKey(mapKey)) { + keyToCommandHashes.get(mapKey).add(hash); } else { Set set = new HashSet<>(); set.add(hash); - keyHashes.put(mapKey, set); + keyToCommandHashes.put(mapKey, set); } } } @@ -82,11 +82,11 @@ final T getValue(Function, T> loader, CommandObject comm protected abstract long getHash(CommandObject command); - private ByteBuffer makeKey(String key) { - return makeKey(SafeEncoder.encode(key)); + private ByteBuffer makeKeyForKeyToCommandHashes(String key) { + return makeKeyForKeyToCommandHashes(SafeEncoder.encode(key)); } - private static ByteBuffer makeKey(byte[] b) { + private static ByteBuffer makeKeyForKeyToCommandHashes(byte[] b) { return ByteBuffer.wrap(b); } } From fafca797f4ff4461cdcc5ae069075962f8470860 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:46:06 +0600 Subject: [PATCH 15/16] descriptive names and fix --- .../redis/clients/jedis/ClientSideCache.java | 31 ++++++++++++------- .../clients/jedis/JedisClusterInfoCache.java | 2 +- .../SentineledConnectionProvider.java | 2 +- .../redis/clients/jedis/util/CaffeineCSC.java | 6 ++-- .../redis/clients/jedis/util/GuavaCSC.java | 6 ++-- .../java/redis/clients/jedis/util/MapCSC.java | 6 ++-- 6 files changed, 31 insertions(+), 22 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 45db9d83e2..01e5fb669c 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -22,19 +22,34 @@ protected ClientSideCache() { this.keyToCommandHashes = new ConcurrentHashMap<>(); } - public abstract void invalidateAll(); + protected abstract void invalidateAllCommandHashes(); - protected abstract void invalidateAll(Iterable hashes); + protected abstract void invalidateCommandHashes(Iterable hashes); + + protected abstract void put(long hash, Object value); + + protected abstract Object get(long hash); + + protected abstract long getCommandHash(CommandObject command); + + public final void clear() { + invalidateAllKeysAndCommandHashes(); + } final void invalidate(List list) { if (list == null) { - invalidateAll(); + invalidateAllKeysAndCommandHashes(); return; } list.forEach(this::invalidateKeyAndRespectiveCommandHashes); } + private void invalidateAllKeysAndCommandHashes() { + invalidateAllCommandHashes(); + keyToCommandHashes.clear(); + } + private void invalidateKeyAndRespectiveCommandHashes(Object key) { if (!(key instanceof byte[])) { throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key)); @@ -44,18 +59,14 @@ private void invalidateKeyAndRespectiveCommandHashes(Object key) { Set hashes = keyToCommandHashes.get(mapKey); if (hashes != null) { - invalidateAll(hashes); + invalidateCommandHashes(hashes); keyToCommandHashes.remove(mapKey); } } - protected abstract void put(long hash, Object value); - - protected abstract Object get(long hash); - final T getValue(Function, T> loader, CommandObject command, String... keys) { - final long hash = getHash(command); + final long hash = getCommandHash(command); T value = (T) get(hash); if (value != null) { @@ -80,8 +91,6 @@ final T getValue(Function, T> loader, CommandObject comm return value; } - protected abstract long getHash(CommandObject command); - private ByteBuffer makeKeyForKeyToCommandHashes(String key) { return makeKeyForKeyToCommandHashes(SafeEncoder.encode(key)); } diff --git a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java index 9402b150ba..5646dbfb59 100644 --- a/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java +++ b/src/main/java/redis/clients/jedis/JedisClusterInfoCache.java @@ -227,7 +227,7 @@ private void discoverClusterSlots(Connection jedis) { Arrays.fill(slots, null); Arrays.fill(slotNodes, null); if (clientSideCache != null) { - clientSideCache.invalidateAll(); + clientSideCache.clear(); } Set hostAndPortKeys = new HashSet<>(); diff --git a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java index ae883e2af3..e335803b62 100644 --- a/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java +++ b/src/main/java/redis/clients/jedis/providers/SentineledConnectionProvider.java @@ -128,7 +128,7 @@ private void initMaster(HostAndPort master) { pool = newPool; LOG.info("Created connection pool to master at {}.", master); if (clientSideCache != null) { - clientSideCache.invalidateAll(); + clientSideCache.clear(); } if (existingPool != null) { diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index 36f354bc4a..e8de08a654 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -23,12 +23,12 @@ public CaffeineCSC(Cache caffeineCache, LongHashFunction hashFunct } @Override - public final void invalidateAll() { + protected final void invalidateAllCommandHashes() { cache.invalidateAll(); } @Override - protected void invalidateAll(Iterable hashes) { + protected void invalidateCommandHashes(Iterable hashes) { cache.invalidateAll(hashes); } @@ -43,7 +43,7 @@ protected Object get(long hash) { } @Override - protected final long getHash(CommandObject command) { + protected final long getCommandHash(CommandObject command) { long[] nums = new long[command.getArguments().size() + 1]; int idx = 0; for (Rawable raw : command.getArguments()) { diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java index 643c62b9a9..8376964d22 100644 --- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -23,12 +23,12 @@ public GuavaCSC(Cache guavaCache, HashFunction hashFunction) { } @Override - public final void invalidateAll() { + protected final void invalidateAllCommandHashes() { cache.invalidateAll(); } @Override - protected void invalidateAll(Iterable hashes) { + protected void invalidateCommandHashes(Iterable hashes) { cache.invalidateAll(hashes); } @@ -43,7 +43,7 @@ protected Object get(long hash) { } @Override - protected final long getHash(CommandObject command) { + protected final long getCommandHash(CommandObject command) { Hasher hasher = function.newHasher(); command.getArguments().forEach(raw -> hasher.putBytes(raw.getRaw())); hasher.putInt(command.getBuilder().hashCode()); diff --git a/src/test/java/redis/clients/jedis/util/MapCSC.java b/src/test/java/redis/clients/jedis/util/MapCSC.java index 0915fd9050..eb229036ea 100644 --- a/src/test/java/redis/clients/jedis/util/MapCSC.java +++ b/src/test/java/redis/clients/jedis/util/MapCSC.java @@ -20,12 +20,12 @@ public MapCSC(Map map) { } @Override - public final void invalidateAll() { + protected final void invalidateAllCommandHashes() { cache.clear(); } @Override - protected void invalidateAll(Iterable hashes) { + protected void invalidateCommandHashes(Iterable hashes) { hashes.forEach(hash -> cache.remove(hash)); } @@ -40,7 +40,7 @@ protected Object get(long hash) { } @Override - protected final long getHash(CommandObject command) { + protected final long getCommandHash(CommandObject command) { long result = 1; for (Rawable raw : command.getArguments()) { result = 31 * result + Arrays.hashCode(raw.getRaw()); From b82840a9d1da20fdec7f2acaf4e5ee4213a7e9e7 Mon Sep 17 00:00:00 2001 From: M Sazzadul Hoque <7600764+sazzad16@users.noreply.github.com> Date: Tue, 13 Feb 2024 00:48:21 +0600 Subject: [PATCH 16/16] common default values in base class --- src/main/java/redis/clients/jedis/ClientSideCache.java | 3 +++ src/main/java/redis/clients/jedis/util/CaffeineCSC.java | 2 -- src/main/java/redis/clients/jedis/util/GuavaCSC.java | 2 -- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/main/java/redis/clients/jedis/ClientSideCache.java b/src/main/java/redis/clients/jedis/ClientSideCache.java index 01e5fb669c..c2c9248acf 100644 --- a/src/main/java/redis/clients/jedis/ClientSideCache.java +++ b/src/main/java/redis/clients/jedis/ClientSideCache.java @@ -16,6 +16,9 @@ */ public abstract class ClientSideCache { + protected static final int DEFAULT_MAXIMUM_SIZE = 10_000; + protected static final int DEFAULT_EXPIRE_SECONDS = 100; + private final Map> keyToCommandHashes; protected ClientSideCache() { diff --git a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java index e8de08a654..3bce3504b3 100644 --- a/src/main/java/redis/clients/jedis/util/CaffeineCSC.java +++ b/src/main/java/redis/clients/jedis/util/CaffeineCSC.java @@ -10,8 +10,6 @@ public class CaffeineCSC extends ClientSideCache { - private static final int DEFAULT_MAXIMUM_SIZE = 10_000; - private static final int DEFAULT_EXPIRE_SECONDS = 100; private static final LongHashFunction DEFAULT_HASH_FUNCTION = LongHashFunction.xx3(); private final Cache cache; diff --git a/src/main/java/redis/clients/jedis/util/GuavaCSC.java b/src/main/java/redis/clients/jedis/util/GuavaCSC.java index 8376964d22..d9973b7dc6 100644 --- a/src/main/java/redis/clients/jedis/util/GuavaCSC.java +++ b/src/main/java/redis/clients/jedis/util/GuavaCSC.java @@ -10,8 +10,6 @@ public class GuavaCSC extends ClientSideCache { - private static final int DEFAULT_MAXIMUM_SIZE = 10_000; - private static final int DEFAULT_EXPIRE_SECONDS = 100; private static final HashFunction DEFAULT_HASH_FUNCTION = com.google.common.hash.Hashing.fingerprint2011(); private final Cache cache;