You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@hbase.apache.org by ps...@apache.org on 2026/09/25 09:01:53 UTC
(hbase) branch HBASE-30018 updated: HBASE-30384 Add dynamic cache sizing support for CacheEngine-based caches (#8702)
This is an automated email from the ASF dual-hosted git repository.
petersomogyi pushed a commit to branch HBASE-30018
in repository https://gitbox.apache.org/repos/asf/hbase.git
The following commit(s) were added to refs/heads/HBASE-30018 by this push:
new 4fac6b8e932 HBASE-30384 Add dynamic cache sizing support for CacheEngine-based caches (#8702)
4fac6b8e932 is described below
commit 4fac6b8e932cad5aa2ad3819829a38517f46e64b
Author: Vladimir Rodionov <vl...@gmail.com>
AuthorDate: Fri Sep 25 02:01:46 2026 -0700
HBASE-30384 Add dynamic cache sizing support for CacheEngine-based caches (#8702)
Signed-off-by: Peter Somogyi <ps...@apache.org>
---
.../hadoop/hbase/io/hfile/cache/CacheEngines.java | 4 +++
.../hbase/io/hfile/cache/LruCacheEngine.java | 3 +-
...a => ResizableBlockCacheBackedCacheEngine.java} | 34 +++++++++++++---------
...CacheEngines.java => ResizableCacheEngine.java} | 28 +++++++-----------
.../hbase/io/hfile/cache/TestCacheEngines.java | 29 ++++++++++++++++--
5 files changed, 63 insertions(+), 35 deletions(-)
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
index a9707b11676..add7a69c385 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
@@ -19,6 +19,7 @@ package org.apache.hadoop.hbase.io.hfile.cache;
import java.util.Objects;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
+import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache;
import org.apache.yetus.audience.InterfaceAudience;
/**
@@ -43,6 +44,9 @@ public final class CacheEngines {
*/
public static CacheEngine fromBlockCache(BlockCache blockCache) {
Objects.requireNonNull(blockCache, "blockCache must not be null");
+ if (blockCache instanceof ResizableBlockCache) {
+ return new ResizableBlockCacheBackedCacheEngine((ResizableBlockCache) blockCache);
+ }
return new BlockCacheBackedCacheEngine(blockCache);
}
}
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/LruCacheEngine.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/LruCacheEngine.java
index 2717a555314..53ad44e45d5 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/LruCacheEngine.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/LruCacheEngine.java
@@ -88,7 +88,7 @@ import org.apache.hbase.thirdparty.com.google.common.util.concurrent.ThreadFacto
* </p>
*/
@InterfaceAudience.Private
-public class LruCacheEngine implements CacheEngine, HeapSize, Iterable<CachedBlock> {
+public class LruCacheEngine implements ResizableCacheEngine, HeapSize, Iterable<CachedBlock> {
private static final Logger LOG = LoggerFactory.getLogger(LruCacheEngine.class);
@@ -376,6 +376,7 @@ public class LruCacheEngine implements CacheEngine, HeapSize, Iterable<CachedBlo
* </p>
* @param maxSize new maximum size, in bytes
*/
+ @Override
public void setMaxSize(long maxSize) {
this.maxSize = maxSize;
if (size.get() > acceptableSize() && !evictionInProgress) {
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableBlockCacheBackedCacheEngine.java
similarity index 50%
copy from hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
copy to hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableBlockCacheBackedCacheEngine.java
index a9707b11676..87627fe8ed4 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableBlockCacheBackedCacheEngine.java
@@ -18,31 +18,37 @@
package org.apache.hadoop.hbase.io.hfile.cache;
import java.util.Objects;
-import org.apache.hadoop.hbase.io.hfile.BlockCache;
+import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache;
import org.apache.yetus.audience.InterfaceAudience;
/**
- * Factory helpers for {@link CacheEngine} instances.
+ * A {@link CacheEngine} adapter for a legacy {@link ResizableBlockCache}.
* <p>
- * These helpers are intended to keep transitional wiring concise while existing cache
- * implementations are still based on {@link BlockCache}. Once built-in caches implement
- * {@link CacheEngine} directly, callers can construct or obtain those engines without going through
- * a legacy adapter.
+ * This adapter preserves the dynamic sizing capability while legacy block caches are being migrated
+ * to native {@link CacheEngine} implementations.
* </p>
*/
@InterfaceAudience.Private
-public final class CacheEngines {
+public class ResizableBlockCacheBackedCacheEngine extends BlockCacheBackedCacheEngine
+ implements ResizableCacheEngine {
- private CacheEngines() {
+ private final ResizableBlockCache blockCache;
+
+ /**
+ * Creates an engine backed by the supplied resizable block cache.
+ * @param blockCache legacy resizable block cache
+ */
+ public ResizableBlockCacheBackedCacheEngine(ResizableBlockCache blockCache) {
+ super(Objects.requireNonNull(blockCache, "blockCache must not be null"));
+ this.blockCache = blockCache;
}
/**
- * Wraps an existing {@link BlockCache} as a {@link CacheEngine}.
- * @param blockCache block cache to adapt
- * @return cache engine backed by the supplied block cache
+ * Changes the maximum size of the underlying block cache.
+ * @param maxSize new maximum cache size in bytes
*/
- public static CacheEngine fromBlockCache(BlockCache blockCache) {
- Objects.requireNonNull(blockCache, "blockCache must not be null");
- return new BlockCacheBackedCacheEngine(blockCache);
+ @Override
+ public void setMaxSize(long maxSize) {
+ blockCache.setMaxSize(maxSize);
}
}
diff --git a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableCacheEngine.java
similarity index 52%
copy from hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
copy to hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableCacheEngine.java
index a9707b11676..e650fee201c 100644
--- a/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/CacheEngines.java
+++ b/hbase-server/src/main/java/org/apache/hadoop/hbase/io/hfile/cache/ResizableCacheEngine.java
@@ -17,32 +17,24 @@
*/
package org.apache.hadoop.hbase.io.hfile.cache;
-import java.util.Objects;
-import org.apache.hadoop.hbase.io.hfile.BlockCache;
import org.apache.yetus.audience.InterfaceAudience;
/**
- * Factory helpers for {@link CacheEngine} instances.
+ * A {@link CacheEngine} whose maximum size can be changed at runtime.
* <p>
- * These helpers are intended to keep transitional wiring concise while existing cache
- * implementations are still based on {@link BlockCache}. Once built-in caches implement
- * {@link CacheEngine} directly, callers can construct or obtain those engines without going through
- * a legacy adapter.
+ * This capability is intentionally separate from {@link CacheEngine}. Cache engines which have a
+ * fixed capacity do not need to implement dynamic sizing.
* </p>
*/
@InterfaceAudience.Private
-public final class CacheEngines {
-
- private CacheEngines() {
- }
+public interface ResizableCacheEngine extends CacheEngine {
/**
- * Wraps an existing {@link BlockCache} as a {@link CacheEngine}.
- * @param blockCache block cache to adapt
- * @return cache engine backed by the supplied block cache
+ * Changes the maximum size of this cache engine.
+ * <p>
+ * Implementations may perform eviction as necessary to bring the cache within the new capacity.
+ * </p>
+ * @param maxSize new maximum cache size in bytes
*/
- public static CacheEngine fromBlockCache(BlockCache blockCache) {
- Objects.requireNonNull(blockCache, "blockCache must not be null");
- return new BlockCacheBackedCacheEngine(blockCache);
- }
+ void setMaxSize(long maxSize);
}
diff --git a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/cache/TestCacheEngines.java b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/cache/TestCacheEngines.java
index bd9d0bb49c1..2002e9ef2b0 100644
--- a/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/cache/TestCacheEngines.java
+++ b/hbase-server/src/test/java/org/apache/hadoop/hbase/io/hfile/cache/TestCacheEngines.java
@@ -17,12 +17,16 @@
*/
package org.apache.hadoop.hbase.io.hfile.cache;
+import static org.junit.jupiter.api.Assertions.assertFalse;
+import static org.junit.jupiter.api.Assertions.assertInstanceOf;
import static org.junit.jupiter.api.Assertions.assertSame;
import static org.junit.jupiter.api.Assertions.assertThrows;
import static org.junit.jupiter.api.Assertions.assertTrue;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
import org.apache.hadoop.hbase.io.hfile.BlockCache;
+import org.apache.hadoop.hbase.io.hfile.ResizableBlockCache;
import org.apache.hadoop.hbase.testclassification.IOTests;
import org.apache.hadoop.hbase.testclassification.SmallTests;
import org.junit.jupiter.api.Tag;
@@ -35,9 +39,7 @@ class TestCacheEngines {
@Test
void testFromBlockCacheReturnsBlockCacheBackedCacheEngine() {
BlockCache blockCache = mock(BlockCache.class);
-
CacheEngine engine = CacheEngines.fromBlockCache(blockCache);
-
assertTrue(engine instanceof BlockCacheBackedCacheEngine);
assertSame(blockCache, ((BlockCacheBackedCacheEngine) engine).getBlockCache());
}
@@ -46,4 +48,27 @@ class TestCacheEngines {
void testFromBlockCacheRejectsNull() {
assertThrows(NullPointerException.class, () -> CacheEngines.fromBlockCache(null));
}
+
+ /**
+ * Verifies that adapting a resizable legacy block cache preserves its dynamic sizing capability.
+ */
+ @Test
+ public void testResizableBlockCachePreservesResizeCapability() {
+ ResizableBlockCache blockCache = mock(ResizableBlockCache.class);
+ CacheEngine engine = CacheEngines.fromBlockCache(blockCache);
+ assertInstanceOf(ResizableCacheEngine.class, engine);
+ ResizableCacheEngine resizableEngine = (ResizableCacheEngine) engine;
+ resizableEngine.setMaxSize(12345L);
+ verify(blockCache).setMaxSize(12345L);
+ }
+
+ /**
+ * Verifies that adapting a non-resizable legacy block cache does not expose dynamic sizing.
+ */
+ @Test
+ public void testNonResizableBlockCacheDoesNotExposeResizeCapability() {
+ BlockCache blockCache = mock(BlockCache.class);
+ CacheEngine engine = CacheEngines.fromBlockCache(blockCache);
+ assertFalse(engine instanceof ResizableCacheEngine);
+ }
}