diff --git a/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/state/ReadableKVStateBase.java b/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/state/ReadableKVStateBase.java index a5619ad5dd31..023d8a145a43 100644 --- a/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/state/ReadableKVStateBase.java +++ b/hedera-node/hedera-app-spi/src/main/java/com/hedera/node/app/spi/state/ReadableKVStateBase.java @@ -19,6 +19,8 @@ import edu.umd.cs.findbugs.annotations.NonNull; import edu.umd.cs.findbugs.annotations.Nullable; import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.ConcurrentMap; /** * A base class for implementations of {@link ReadableKVState} and {@link WritableKVState}. @@ -38,10 +40,12 @@ public abstract class ReadableKVStateBase implements ReadableKVState * changed before we got to handle transaction. If the value is "null", this means it was NOT * FOUND when we looked it up. */ - private final Map readCache = Collections.synchronizedMap(new HashMap<>()); + private final ConcurrentMap readCache = new ConcurrentHashMap<>(); private final Set unmodifiableReadKeys = Collections.unmodifiableSet(readCache.keySet()); + private static final Object marker = new Object(); + /** * Create a new StateBase. * @@ -69,7 +73,8 @@ public V get(@NonNull K key) { final var value = readFromDataSource(key); markRead(key, value); } - return readCache.get(key); + final var value = readCache.get(key); + return (value == marker) ? null : value; } /** @@ -121,7 +126,11 @@ public void reset() { * @param value The value */ protected final void markRead(@NonNull K key, @Nullable V value) { - readCache.put(key, value); + if (value == null) { + readCache.put(key, (V) marker); + } else { + readCache.put(key, value); + } } /**