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 c9fd15d2cb7..96a4e122f7a 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 62c5be28c24..482c9c06818 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 ba7b36b134b..343b24c842e 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 00000000000..7a205f40ab0
--- /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 3c8bc18c5ce..8e276d96650 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 ad4313a4b72..805d9738d74 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 9af243ffc7c..5fa5a36f4b1 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 00000000000..a9d1ef6f373
--- /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 96a4e122f7a..c8c8d8149d2 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 7a205f40ab0..d5537cc73bc 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 00000000000..b4e31caa626
--- /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 c8c8d8149d2..1fcb758640a 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 482c9c06818..063087cff54 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 5646dbfb59c..9402b150baf 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 343b24c842e..c7936bfb626 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 e335803b628..ae883e2af33 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 d5537cc73bc..c3364168c77 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 b4e31caa626..e51e0c25f88 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 8e276d96650..2f11af837bf 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 805d9738d74..b5741454db5 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 5fa5a36f4b1..de20a356f9a 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 a9d1ef6f373..1db1a64810a 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 c7936bfb626..3a2dec9d771 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 2f11af837bf..60ddf002d73 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 b5741454db5..2e641e0f3a8 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 de20a356f9a..9e5f720933f 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 063087cff54..d21170afe30 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 d21170afe30..616fe7d7b55 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 4af1261cd40..4bd82fec1ef 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 616fe7d7b55..2b15fb75dfa 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 c3364168c77..c12f7a475bb 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 e51e0c25f88..282c03790e1 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 1db1a64810a..0915fd9050f 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 1fcb758640a..e6ff5bc70b9 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 c12f7a475bb..36f354bc4ac 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 282c03790e1..643c62b9a98 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 2b15fb75dfa..1371a2d3766 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 1371a2d3766..f630e83adaf 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 f630e83adaf..598e853ffb4 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 598e853ffb4..b16babab2db 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 b16babab2db..45db9d83e2e 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 45db9d83e2e..01e5fb669ca 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 9402b150baf..5646dbfb59c 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 ae883e2af33..e335803b628 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 36f354bc4ac..e8de08a6547 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 643c62b9a98..8376964d22f 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 0915fd9050f..eb229036eae 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 01e5fb669ca..c2c9248acf4 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 e8de08a6547..3bce3504b38 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 8376964d22f..d9973b7dc60 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;