From f40ced46464a8157c91ddfbcf44665df05a25f0b Mon Sep 17 00:00:00 2001 From: Elijah Wright Date: Tue, 3 Jun 2025 10:46:26 -0700 Subject: [PATCH] replace HashMap with ConcurrentHashMap --- .../api/io/memory/MemoryIOLocation.java | 35 +++++-------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/direct-file/backend/src/main/java/gov/irs/directfile/api/io/memory/MemoryIOLocation.java b/direct-file/backend/src/main/java/gov/irs/directfile/api/io/memory/MemoryIOLocation.java index 345eadd..3ee5d01 100644 --- a/direct-file/backend/src/main/java/gov/irs/directfile/api/io/memory/MemoryIOLocation.java +++ b/direct-file/backend/src/main/java/gov/irs/directfile/api/io/memory/MemoryIOLocation.java @@ -3,8 +3,8 @@ package gov.irs.directfile.api.io.memory; import java.io.ByteArrayInputStream; import java.io.IOException; import java.io.InputStream; -import java.util.HashMap; import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; import lombok.extern.slf4j.Slf4j; @@ -18,36 +18,18 @@ public class MemoryIOLocation implements IIOLocation { // don't use it as a cache, because the stream copy isn't performant. // it is still better than getting files off of disk. // Locations are meant for heavy IO operations - Map writtenData; + Map writtenData; public MemoryIOLocation() { - writtenData = new HashMap<>(); + writtenData = new ConcurrentHashMap<>(); } @Override public InputStream read(String location) throws IOLocationException { - if (writtenData.containsKey(location)) { - var stream = writtenData.get(location); - // we might hit a case where multiple threads try to read from the same stream - // at the same time. We don't want a partial read. There are better ways of solving - // this, but this is a quick way. If this performs anything like dotnet, this will show - // itself as a bottleneck by increasing the background thread count beyond normal levels. - // The read should be fast enough that it doesn't really matter, but I'd like to be certain. - // P.S. I don't care about writing as much in this context, but if write becomes important - // then you will need to sync that too. - synchronized (stream) { - try { - // We cannot hand out the original stream, as we don't know the stateCode - // they will return it in. We want to have it fresh and ready for each call - // so we pass out a copy and reset ours for the next call - log.info("In memory information found at {}! Copying bytes to a new buffer", location); - var bytes = stream.readAllBytes(); - stream.reset(); - return new ByteArrayInputStream(bytes); - } catch (IOException e) { - throw new IOLocationException("In memory location couldn't copy bytes to allow reading", e); - } - } + byte[] bytes = writtenData.get(location); + if (bytes != null) { + log.info("In memory information found at {}! Copying bytes to a new buffer", location); + return new ByteArrayInputStream(bytes); } throw new IOLocationException( String.format("Did not write data to in memory location %s before reading", location)); @@ -64,9 +46,8 @@ public class MemoryIOLocation implements IIOLocation { } catch (IOException e) { throw new IOLocationException("Could not write bytes to in memory stream", e); } - var stream = new ByteArrayInputStream(bytes); log.info("Adding in memory byte stream at {}", location); - writtenData.put(location, stream); + writtenData.put(location, bytes); } @Override