Skip to content

Commit

Permalink
Merge branch '5.2.0' into csc-all-commands
Browse files Browse the repository at this point in the history
  • Loading branch information
sazzad16 committed Feb 15, 2024
2 parents 52d80cb + 5f1d8c6 commit f3bbc8f
Show file tree
Hide file tree
Showing 6 changed files with 60 additions and 58 deletions.
92 changes: 49 additions & 43 deletions src/main/java/redis/clients/jedis/ClientSideCache.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,58 +6,71 @@
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;

/**
* 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<ByteBuffer, Set<Long>> keyHashes;
private final ReentrantLock writeLock = new ReentrantLock();
protected static final int DEFAULT_MAXIMUM_SIZE = 10_000;
protected static final int DEFAULT_EXPIRE_SECONDS = 100;

private final Map<ByteBuffer, Set<Long>> keyToCommandHashes;

protected ClientSideCache() {
this.keyHashes = new ConcurrentHashMap<>();
this.keyToCommandHashes = new ConcurrentHashMap<>();
}

public abstract void invalidateAll();
protected abstract void invalidateAllCommandHashes();

protected abstract void invalidateCommandHashes(Iterable<Long> hashes);

protected abstract void put(long hash, Object value);

protected abstract void invalidateAll(Iterable<Long> hashes);
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::invalidate0);
list.forEach(this::invalidateKeyAndRespectiveCommandHashes);
}

private void invalidate0(Object key) {
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));
}

final ByteBuffer mapKey = makeKey0((byte[]) key);
final ByteBuffer mapKey = makeKeyForKeyToCommandHashes((byte[]) key);

Set<Long> hashes = keyHashes.get(mapKey);
Set<Long> hashes = keyToCommandHashes.get(mapKey);
if (hashes != null) {
writeLock.lock();
try {
invalidateAll(hashes);
keyHashes.remove(mapKey);
} finally {
writeLock.unlock();
}
invalidateCommandHashes(hashes);
keyToCommandHashes.remove(mapKey);
}
}

protected abstract void put(long hash, Object value);

protected abstract Object get(long hash);

final <T> T getValue(Function<CommandObject<T>, T> loader, CommandObject<T> command, Object... keys) {

final long hash = getHash(command);
final long hash = getCommandHash(command);

T value = (T) get(hash);
if (value != null) {
Expand All @@ -66,36 +79,29 @@ final <T> T getValue(Function<CommandObject<T>, T> loader, CommandObject<T> comm

value = loader.apply(command);
if (value != null) {
writeLock.lock();
try {
put(hash, value);
for (Object key : keys) {
ByteBuffer mapKey = makeKey(key);
if (keyHashes.containsKey(mapKey)) {
keyHashes.get(mapKey).add(hash);
} else {
Set<Long> set = new HashSet<>();
set.add(hash);
keyHashes.put(mapKey, set);
}
put(hash, value);
for (Object key : keys) {
ByteBuffer mapKey = makeKeyForKeyToCommandHashes(key);
if (keyToCommandHashes.containsKey(mapKey)) {
keyToCommandHashes.get(mapKey).add(hash);
} else {
Set<Long> set = new HashSet<>();
set.add(hash);
keyToCommandHashes.put(mapKey, set);
}
} finally {
writeLock.unlock();
}
}

return value;
}

protected abstract long getHash(CommandObject command);

private ByteBuffer makeKey(Object key) {
if (key instanceof byte[]) return makeKey0((byte[]) key);
else if (key instanceof String) return makeKey0(SafeEncoder.encode((String) key));
private ByteBuffer makeKeyForKeyToCommandHashes(Object key) {
if (key instanceof byte[]) return makeKeyForKeyToCommandHashes((byte[]) key);
else if (key instanceof String) return makeKeyForKeyToCommandHashes(SafeEncoder.encode((String) key));
else throw new AssertionError("" + key.getClass().getSimpleName() + " is not supported. Value: " + String.valueOf(key));
}

private static ByteBuffer makeKey0(byte[] b) {
private static ByteBuffer makeKeyForKeyToCommandHashes(byte[] b) {
return ByteBuffer.wrap(b);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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<String> hostAndPortKeys = new HashSet<>();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/redis/clients/jedis/util/CaffeineCSC.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<Long, Object> cache;
Expand All @@ -23,12 +21,12 @@ public CaffeineCSC(Cache<Long, Object> caffeineCache, LongHashFunction hashFunct
}

@Override
public final void invalidateAll() {
protected final void invalidateAllCommandHashes() {
cache.invalidateAll();
}

@Override
protected void invalidateAll(Iterable<Long> hashes) {
protected void invalidateCommandHashes(Iterable<Long> hashes) {
cache.invalidateAll(hashes);
}

Expand All @@ -43,7 +41,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()) {
Expand Down
8 changes: 3 additions & 5 deletions src/main/java/redis/clients/jedis/util/GuavaCSC.java
Original file line number Diff line number Diff line change
Expand Up @@ -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<Long, Object> cache;
Expand All @@ -23,12 +21,12 @@ public GuavaCSC(Cache<Long, Object> guavaCache, HashFunction hashFunction) {
}

@Override
public final void invalidateAll() {
protected final void invalidateAllCommandHashes() {
cache.invalidateAll();
}

@Override
protected void invalidateAll(Iterable<Long> hashes) {
protected void invalidateCommandHashes(Iterable<Long> hashes) {
cache.invalidateAll(hashes);
}

Expand All @@ -43,7 +41,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());
Expand Down
6 changes: 3 additions & 3 deletions src/test/java/redis/clients/jedis/util/MapCSC.java
Original file line number Diff line number Diff line change
Expand Up @@ -20,12 +20,12 @@ public MapCSC(Map<Long, Object> map) {
}

@Override
public final void invalidateAll() {
protected final void invalidateAllCommandHashes() {
cache.clear();
}

@Override
protected void invalidateAll(Iterable<Long> hashes) {
protected void invalidateCommandHashes(Iterable<Long> hashes) {
hashes.forEach(hash -> cache.remove(hash));
}

Expand All @@ -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());
Expand Down

0 comments on commit f3bbc8f

Please sign in to comment.