This is an automated email from the ASF dual-hosted git repository.
smengcl pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ozone.git
The following commit(s) were added to refs/heads/master by this push:
new 523b93ea1eb HDDS-15357. Fix MappedBufferManager WeakReference races
(#10351)
523b93ea1eb is described below
commit 523b93ea1eb95b0f35d6e0c7d49e30b808f10898
Author: Siyao Meng <[email protected]>
AuthorDate: Wed May 27 20:18:47 2026 -0700
HDDS-15357. Fix MappedBufferManager WeakReference races (#10351)
---
.../keyvalue/impl/MappedBufferManager.java | 23 ++++++++++++++--------
1 file changed, 15 insertions(+), 8 deletions(-)
diff --git
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/MappedBufferManager.java
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/MappedBufferManager.java
index 8186bdb029f..7d2f822e5a5 100644
---
a/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/MappedBufferManager.java
+++
b/hadoop-hdds/container-service/src/main/java/org/apache/hadoop/ozone/container/keyvalue/impl/MappedBufferManager.java
@@ -20,6 +20,7 @@
import com.google.common.util.concurrent.Striped;
import java.lang.ref.WeakReference;
import java.nio.ByteBuffer;
+import java.util.Map;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.Semaphore;
@@ -57,10 +58,14 @@ public boolean getQuota(int permits) {
CompletableFuture.runAsync(() -> {
int p = 0;
try {
- for (String key : mappedBuffers.keySet()) {
- ByteBuffer buf = mappedBuffers.get(key).get();
- if (buf == null) {
- mappedBuffers.remove(key);
+ // remove(key, value) only counts entries we observed cleared,
+ // so a concurrent put() that replaced the WeakReference is not
+ // miscounted as freed.
+ for (Map.Entry<String, WeakReference<ByteBuffer>> entry
+ : mappedBuffers.entrySet()) {
+ final WeakReference<ByteBuffer> ref = entry.getValue();
+ if (ref.get() == null
+ && mappedBuffers.remove(entry.getKey(), ref)) {
p++;
}
}
@@ -93,14 +98,16 @@ public ByteBuffer computeIfAbsent(String file, long
position, long size,
Lock fileLock = lock.get(key);
fileLock.lock();
try {
- WeakReference<ByteBuffer> refer = mappedBuffers.get(key);
- if (refer != null && refer.get() != null) {
- // reuse the mapped buffer
+ // Hold a strong reference for the rest of this method so GC cannot
+ // clear the WeakReference between the null check and the return.
+ final WeakReference<ByteBuffer> refer = mappedBuffers.get(key);
+ final ByteBuffer cached = refer != null ? refer.get() : null;
+ if (cached != null) {
if (LOG.isDebugEnabled()) {
LOG.debug("find buffer for key {}", key);
}
releaseQuota(1);
- return refer.get();
+ return cached;
}
ByteBuffer buffer = supplier.get();
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]