This is an automated email from the ASF dual-hosted git repository.

JingsongLi pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/paimon.git


The following commit(s) were added to refs/heads/master by this push:
     new e7db7cf851 [core] Avoid retaining rejected cache pages (#9658)
e7db7cf851 is described below

commit e7db7cf851880c7ccbd4ce8d760ddf9ce6cf66ce
Author: yuzelin <[email protected]>
AuthorDate: Sun Sep 6 16:07:17 2026 +0800

    [core] Avoid retaining rejected cache pages (#9658)
---
 .../java/org/apache/paimon/io/cache/Cache.java     |  3 ++
 .../org/apache/paimon/io/cache/CacheManager.java   |  8 +++++
 .../org/apache/paimon/io/cache/CaffeineCache.java  |  5 ++++
 .../java/org/apache/paimon/sst/BlockCache.java     |  4 ++-
 .../apache/paimon/io/cache/CacheManagerTest.java   | 35 ++++++++++++++++++++++
 5 files changed, 54 insertions(+), 1 deletion(-)

diff --git a/paimon-common/src/main/java/org/apache/paimon/io/cache/Cache.java 
b/paimon-common/src/main/java/org/apache/paimon/io/cache/Cache.java
index d1def1fec5..8f96cdfba4 100644
--- a/paimon-common/src/main/java/org/apache/paimon/io/cache/Cache.java
+++ b/paimon-common/src/main/java/org/apache/paimon/io/cache/Cache.java
@@ -27,11 +27,14 @@ import java.util.function.Function;
 
 /** Cache interface in Paimon. */
 public interface Cache {
+
     @Nullable
     CacheValue get(CacheKey key, Function<CacheKey, CacheValue> supplier);
 
     void put(CacheKey key, CacheValue value);
 
+    boolean contains(CacheKey key);
+
     void invalidate(CacheKey key);
 
     void invalidateAll();
diff --git 
a/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java 
b/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
index e8cd314725..4fe040e1c5 100644
--- a/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
+++ b/paimon-common/src/main/java/org/apache/paimon/io/cache/CacheManager.java
@@ -102,6 +102,14 @@ public class CacheManager implements AutoCloseable {
         return checkNotNull(value, "Cache result for key(%s) is null", 
key).segment;
     }
 
+    public boolean contains(CacheKey key) {
+        if (key.isIndex()) {
+            return indexCache.contains(key);
+        } else {
+            return dataCache.contains(key);
+        }
+    }
+
     public void invalidPage(CacheKey key) {
         if (key.isIndex()) {
             indexCache.invalidate(key);
diff --git 
a/paimon-common/src/main/java/org/apache/paimon/io/cache/CaffeineCache.java 
b/paimon-common/src/main/java/org/apache/paimon/io/cache/CaffeineCache.java
index 8fda391fcc..3bb47f82ee 100644
--- a/paimon-common/src/main/java/org/apache/paimon/io/cache/CaffeineCache.java
+++ b/paimon-common/src/main/java/org/apache/paimon/io/cache/CaffeineCache.java
@@ -47,6 +47,11 @@ public class CaffeineCache implements Cache {
         this.cache.put(key, value);
     }
 
+    @Override
+    public boolean contains(CacheKey key) {
+        return this.cache.policy().getIfPresentQuietly(key) != null;
+    }
+
     @Override
     public void invalidate(CacheKey key) {
         this.cache.invalidate(key);
diff --git a/paimon-common/src/main/java/org/apache/paimon/sst/BlockCache.java 
b/paimon-common/src/main/java/org/apache/paimon/sst/BlockCache.java
index 65a6838db7..32e341bbd6 100644
--- a/paimon-common/src/main/java/org/apache/paimon/sst/BlockCache.java
+++ b/paimon-common/src/main/java/org/apache/paimon/sst/BlockCache.java
@@ -79,7 +79,9 @@ public class BlockCache implements Closeable {
                             },
                             blocks::remove);
             container = new SegmentContainer(segment);
-            blocks.put(cacheKey, container);
+            if (cacheManager.contains(cacheKey)) {
+                blocks.put(cacheKey, container);
+            }
         }
         return container.access();
     }
diff --git 
a/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java 
b/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
index e8ca35271e..662978a3f5 100644
--- 
a/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
+++ 
b/paimon-common/src/test/java/org/apache/paimon/io/cache/CacheManagerTest.java
@@ -18,8 +18,10 @@
 
 package org.apache.paimon.io.cache;
 
+import org.apache.paimon.fs.ByteArraySeekableStream;
 import org.apache.paimon.memory.MemorySegment;
 import org.apache.paimon.options.MemorySize;
+import org.apache.paimon.sst.BlockCache;
 
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.Timeout;
@@ -29,6 +31,7 @@ import java.io.File;
 import java.io.RandomAccessFile;
 import java.nio.file.Path;
 import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicInteger;
 
 import static org.assertj.core.api.Assertions.assertThat;
 
@@ -67,6 +70,38 @@ public class CacheManagerTest {
         }
     }
 
+    @Test
+    void testRejectedPageNotRetainedByBlockCache() throws Exception {
+        int pageSize = 1024;
+        int hotPages = 64;
+        int totalPages = 10_000;
+        byte[] data = new byte[pageSize * totalPages];
+        org.apache.paimon.fs.Path file = new org.apache.paimon.fs.Path("file");
+        AtomicInteger invalidatedPages = new AtomicInteger();
+        CacheManager cacheManager =
+                new CacheManager(MemorySize.ofKibiBytes(64), 0) {
+                    @Override
+                    public void invalidPage(CacheKey key) {
+                        invalidatedPages.incrementAndGet();
+                        super.invalidPage(key);
+                    }
+                };
+        BlockCache blockCache =
+                new BlockCache(file, new ByteArraySeekableStream(data), 
cacheManager);
+
+        for (int round = 0; round < 100; round++) {
+            for (int page = 0; page < hotPages; page++) {
+                blockCache.getBlock(page * pageSize, pageSize, bytes -> bytes, 
false);
+            }
+        }
+        for (int page = hotPages; page < totalPages; page++) {
+            blockCache.getBlock(page * pageSize, pageSize, bytes -> bytes, 
false);
+        }
+
+        blockCache.close();
+        assertThat(invalidatedPages).hasValue(hotPages);
+    }
+
     @Test
     void testOffHeapCache() throws Exception {
         File file = new File(tempDir.toFile(), "test.off-heap");

Reply via email to