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]

Reply via email to