This is an automated email from the ASF dual-hosted git repository.
zhangstar333 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/doris.git
The following commit(s) were added to refs/heads/master by this push:
new 7f016da4626 [fix](regression) Isolate external file cache test state
(#69701)
7f016da4626 is described below
commit 7f016da46263748828f175f5907c18aca412de5c
Author: Gabriel <[email protected]>
AuthorDate: Wed Oct 28 11:13:24 2026 +0800
[fix](regression) Isolate external file cache test state (#69701)
### What problem does this PR solve?
The external file-cache tests depend on host disk/inode usage and
inherited backend settings. Under resource-limit or advance-eviction
mode, cache blocks can disappear between reads: the query-limit test
observes an empty queue, the statistics test cannot establish stable
hit/read counts, and the feature test times out while waiting for
default flags to become zero.
Establish a scoped baseline for these three non-concurrent suites.
Disable upper read caches and inherited per-query limits, temporarily
suppress advance eviction, and use 100% disk thresholds while retaining
the failure for a genuinely full filesystem. Poll both mode flags across
cache paths before measuring data. Restore every backend setting through
the existing temporary-config helper, including on assertion failure.
For the feature test, drive resource-limit entry with zero thresholds
and advance-eviction entry with a one-percent threshold. A populated
cache directory consumes an inode, whose used percentage rounds up to at
least one. Nest threshold updates so the background monitor never
observes an invalid enter/exit ordering during application or
restoration. Keep the existing query results and cache assertions.
---
.../plugins/file_cache_test_plugin.groovy | 57 ++
.../cache/test_file_cache_features.groovy | 202 ++++---
.../cache/test_file_cache_query_limit.groovy | 586 ++++++++++-----------
.../cache/test_file_cache_statistics.groovy | 236 ++++-----
4 files changed, 563 insertions(+), 518 deletions(-)
diff --git a/regression-test/plugins/file_cache_test_plugin.groovy
b/regression-test/plugins/file_cache_test_plugin.groovy
new file mode 100644
index 00000000000..2b86153c0ee
--- /dev/null
+++ b/regression-test/plugins/file_cache_test_plugin.groovy
@@ -0,0 +1,57 @@
+// Licensed to the Apache Software Foundation (ASF) under one
+// or more contributor license agreements. See the NOTICE file
+// distributed with this work for additional information
+// regarding copyright ownership. The ASF licenses this file
+// to you under the Apache License, Version 2.0 (the
+// "License"); you may not use this file except in compliance
+// with the License. You may obtain a copy of the License at
+//
+// http://www.apache.org/licenses/LICENSE-2.0
+//
+// Unless required by applicable law or agreed to in writing,
+// software distributed under the License is distributed on an
+// "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+// KIND, either express or implied. See the License for the
+// specific language governing permissions and limitations
+// under the License.
+
+import org.apache.doris.regression.suite.Suite
+
+// Use only in nonConcurrent suites: backend configuration is shared by all
queries.
+Suite.metaClass.withStableFileCache = { Closure action ->
+ Suite suite = delegate as Suite
+ // Disable upper caches so repeated reads reach BlockFileCache.
+ suite.sql "set enable_file_cache = true"
+ suite.sql "set disable_file_cache = false"
+ suite.sql "set enable_sql_cache = false"
+ suite.sql "set enable_hive_sql_cache = false"
+ suite.sql "set enable_query_cache = false"
+ suite.sql "set enable_parquet_file_page_cache = false"
+
+ long monitorMs =
suite.get_be_param("file_cache_background_monitor_interval_ms")
+ .values().collect { it.toLong() }.max()
+ int timeoutSeconds = Math.max(30, (monitorMs * 6L / 1000L) as int)
+ // Host disk pressure and inherited query limits must not evict the blocks
being measured.
+ // Keep a real full disk visible: 100% still enters resource limit mode.
+ suite.setBeConfigTemporary([
+ "enable_evict_file_cache_in_advance": "false",
+ "enable_file_cache_query_limit": "false"
+ ]) {
+ // Nest the thresholds so both application and restoration preserve
enter >= exit.
+
suite.setBeConfigTemporary(["file_cache_enter_disk_resource_limit_mode_percent":
"100"]) {
+
suite.setBeConfigTemporary(["file_cache_exit_disk_resource_limit_mode_percent":
"100"]) {
+ suite.awaitUntil(timeoutSeconds, 1) {
+ def modes = suite.sql """select CACHE_PATH, METRIC_NAME,
METRIC_VALUE
+ from information_schema.file_cache_statistics
+ where METRIC_NAME in ('disk_resource_limit_mode',
'need_evict_cache_in_advance')
+ order by CACHE_PATH, METRIC_NAME"""
+ suite.logger.info("File cache test baseline modes:
${modes}")
+ return !modes.isEmpty() && modes.every {
it[2].toString().toDouble() == 0.0 }
+ }
+ action.call()
+ }
+ }
+ }
+}
+
+logger.info("Added 'withStableFileCache' function to Suite")
diff --git
a/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
b/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
index 45a0e6b4a4d..92947b3d8ef 100644
---
a/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
+++
b/regression-test/suites/external_table_p0/cache/test_file_cache_features.groovy
@@ -31,122 +31,114 @@ suite("test_file_cache_features",
"p0,external,nonConcurrent") {
return;
}
- sql """set enable_file_cache=true"""
- sql """set disable_file_cache=false"""
-
- // Check backend configuration prerequisites
- // Note: This test case assumes a single backend scenario. Testing with
single backend is logically equivalent
- // to testing with multiple backends having identical configurations, but
simpler in logic.
- def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
- logger.info("enable_file_cache configuration: " + enableFileCacheResult)
- assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
- ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-
- def fileCachePathResult = sql """show backend config like
'file_cache_path';"""
- logger.info("file_cache_path configuration: " + fileCachePathResult)
- assertFalse(fileCachePathResult.size() == 0 || fileCachePathResult[0][3]
== null || fileCachePathResult[0][3].trim().isEmpty(),
- FILE_CACHE_PATH_CHECK_FAILED_MSG)
-
- String catalog_name = "test_file_cache_features"
- String ex_db_name = "`tpch1_parquet`"
- String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
- String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
-
- def cacheMetricMax = { String metricName ->
- def r = sql """select max(cast(METRIC_VALUE as double)) from
information_schema.file_cache_statistics
- where METRIC_NAME = '${metricName}';"""
- return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
- }
+ withStableFileCache {
+
+ // Check backend configuration prerequisites
+ // Note: This test case assumes a single backend scenario. Testing
with single backend is logically equivalent
+ // to testing with multiple backends having identical configurations,
but simpler in logic.
+ def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
+ logger.info("enable_file_cache configuration: " +
enableFileCacheResult)
+ assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+ ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+ def fileCachePathResult = sql """show backend config like
'file_cache_path';"""
+ logger.info("file_cache_path configuration: " + fileCachePathResult)
+ assertFalse(fileCachePathResult.size() == 0 ||
fileCachePathResult[0][3] == null || fileCachePathResult[0][3].trim().isEmpty(),
+ FILE_CACHE_PATH_CHECK_FAILED_MSG)
+
+ String catalog_name = "test_file_cache_features"
+ String ex_db_name = "`tpch1_parquet`"
+ String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+ String hms_port = context.config.otherConfigs.get(hivePrefix +
"HmsPort")
+
+ def cacheMetricMax = { String metricName ->
+ def r = sql """select max(cast(METRIC_VALUE as double)) from
information_schema.file_cache_statistics
+ where METRIC_NAME = '${metricName}';"""
+ return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
+ }
- sql """drop catalog if exists ${catalog_name} """
-
- sql """CREATE CATALOG ${catalog_name} PROPERTIES (
- 'type'='hms',
- 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
- 'hadoop.username' = 'hive'
- );"""
-
- sql """switch ${catalog_name}"""
- sql """select l_returnflag, l_linestatus,
- sum(l_quantity) as sum_qty,
- sum(l_extendedprice) as sum_base_price,
- sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
- sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as sum_charge,
- avg(l_quantity) as avg_qty,
- avg(l_extendedprice) as avg_price,
- avg(l_discount) as avg_disc,
- count(*) as count_order
- from ${catalog_name}.${ex_db_name}.lineitem
- where l_shipdate <= date '1998-12-01' - interval '90' day
- group by l_returnflag, l_linestatus
- order by l_returnflag, l_linestatus;"""
-
- def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
- logger.info("file_cache_background_monitor_interval_ms configuration: " +
fileCacheBackgroundMonitorIntervalMsResult)
- assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
- fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
"file_cache_background_monitor_interval_ms is empty or not set to true")
-
- def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
- int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
-
- awaitUntil(pollTimeoutSeconds, 1) {
- return cacheMetricMax('disk_resource_limit_mode') != null &&
- cacheMetricMax('need_evict_cache_in_advance') != null &&
- cacheMetricMax('disk_resource_limit_mode') == 0.0 &&
- cacheMetricMax('need_evict_cache_in_advance') == 0.0
- }
+ sql """drop catalog if exists ${catalog_name} """
+
+ sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+ 'type'='hms',
+ 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+ 'hadoop.username' = 'hive'
+ );"""
+
+ sql """switch ${catalog_name}"""
+ sql """select l_returnflag, l_linestatus,
+ sum(l_quantity) as sum_qty,
+ sum(l_extendedprice) as sum_base_price,
+ sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
+ sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as
sum_charge,
+ avg(l_quantity) as avg_qty,
+ avg(l_extendedprice) as avg_price,
+ avg(l_discount) as avg_disc,
+ count(*) as count_order
+ from ${catalog_name}.${ex_db_name}.lineitem
+ where l_shipdate <= date '1998-12-01' - interval '90' day
+ group by l_returnflag, l_linestatus
+ order by l_returnflag, l_linestatus;"""
+
+ def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
+ logger.info("file_cache_background_monitor_interval_ms configuration:
" + fileCacheBackgroundMonitorIntervalMsResult)
+ assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
"file_cache_background_monitor_interval_ms is empty or not set to true")
+
+ def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
+ int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
- double initialDiskResourceLimitMode =
cacheMetricMax('disk_resource_limit_mode')
- double initialNeedEvictCacheInAdvance =
cacheMetricMax('need_evict_cache_in_advance')
- logger.info("Initial file cache features values -
disk_resource_limit_mode: ${initialDiskResourceLimitMode}, " +
- "need_evict_cache_in_advance: ${initialNeedEvictCacheInAdvance}")
- assertTrue(initialDiskResourceLimitMode == 0.0,
INITIAL_DISK_RESOURCE_LIMIT_MODE_CHECK_FAILED_MSG)
- assertTrue(initialNeedEvictCacheInAdvance == 0.0,
INITIAL_NEED_EVICT_CACHE_IN_ADVANCE_CHECK_FAILED_MSG)
-
- // Set backend configuration parameters for testing
- setBeConfigTemporary([
- "file_cache_enter_disk_resource_limit_mode_percent": "2",
- "file_cache_exit_disk_resource_limit_mode_percent": "1"
- ]) {
- // Execute test logic with modified configuration
- logger.info("Backend configuration set -
file_cache_enter_disk_resource_limit_mode_percent: 2, " +
- "file_cache_exit_disk_resource_limit_mode_percent: 1")
+ awaitUntil(pollTimeoutSeconds, 1) {
+ return cacheMetricMax('disk_resource_limit_mode') != null &&
+ cacheMetricMax('need_evict_cache_in_advance') != null &&
+ cacheMetricMax('disk_resource_limit_mode') == 0.0 &&
+ cacheMetricMax('need_evict_cache_in_advance') == 0.0
+ }
+
+ double initialDiskResourceLimitMode =
cacheMetricMax('disk_resource_limit_mode')
+ double initialNeedEvictCacheInAdvance =
cacheMetricMax('need_evict_cache_in_advance')
+ logger.info("Initial file cache features values -
disk_resource_limit_mode: ${initialDiskResourceLimitMode}, " +
+ "need_evict_cache_in_advance:
${initialNeedEvictCacheInAdvance}")
+ assertTrue(initialDiskResourceLimitMode == 0.0,
INITIAL_DISK_RESOURCE_LIMIT_MODE_CHECK_FAILED_MSG)
+ assertTrue(initialNeedEvictCacheInAdvance == 0.0,
INITIAL_NEED_EVICT_CACHE_IN_ADVANCE_CHECK_FAILED_MSG)
+
+ // Zero thresholds enter on any filesystem. Nest updates to keep enter
>= exit
+ // while applying and restoring settings, even if the monitor runs
between calls.
+
setBeConfigTemporary(["file_cache_exit_disk_resource_limit_mode_percent": "0"])
{
+
setBeConfigTemporary(["file_cache_enter_disk_resource_limit_mode_percent":
"0"]) {
+ awaitUntil(pollTimeoutSeconds, 1) {
+ return cacheMetricMax('disk_resource_limit_mode') != null
&&
+ cacheMetricMax('disk_resource_limit_mode') == 1.0
+ }
+ logger.info("Disk resource limit mode is now active (value =
${cacheMetricMax('disk_resource_limit_mode')})")
+ }
+ }
awaitUntil(pollTimeoutSeconds, 1) {
return cacheMetricMax('disk_resource_limit_mode') != null &&
- cacheMetricMax('disk_resource_limit_mode') == 1.0
+ cacheMetricMax('disk_resource_limit_mode') == 0.0
}
- logger.info("Disk resource limit mode is now active (value =
${cacheMetricMax('disk_resource_limit_mode')})")
- }
- awaitUntil(pollTimeoutSeconds, 1) {
- return cacheMetricMax('disk_resource_limit_mode') != null &&
- cacheMetricMax('disk_resource_limit_mode') == 0.0
- }
-
- // Set backend configuration parameters for need_evict_cache_in_advance
testing
- setBeConfigTemporary([
- "enable_evict_file_cache_in_advance": "true",
- "file_cache_enter_need_evict_cache_in_advance_percent": "2",
- "file_cache_exit_need_evict_cache_in_advance_percent": "1"
- ]) {
- // Execute test logic with modified configuration for
need_evict_cache_in_advance
- logger.info("Backend configuration set for need_evict_cache_in_advance
- " +
- "enable_evict_file_cache_in_advance: true, " +
- "file_cache_enter_need_evict_cache_in_advance_percent: 2, " +
- "file_cache_exit_need_evict_cache_in_advance_percent: 1")
+ // The cache directory consumes an inode, whose used percentage rounds
up to at
+ // least one. This triggers eviction without assuming a busy test-host
disk.
+
setBeConfigTemporary(["file_cache_exit_need_evict_cache_in_advance_percent":
"0"]) {
+ setBeConfigTemporary([
+ "file_cache_enter_need_evict_cache_in_advance_percent": "1",
+ "enable_evict_file_cache_in_advance": "true"
+ ]) {
+ awaitUntil(pollTimeoutSeconds, 1) {
+ return cacheMetricMax('need_evict_cache_in_advance') !=
null &&
+ cacheMetricMax('need_evict_cache_in_advance') ==
1.0
+ }
+ logger.info("Need evict cache in advance mode is now active
(value = ${cacheMetricMax('need_evict_cache_in_advance')})")
+ }
+ }
awaitUntil(pollTimeoutSeconds, 1) {
return cacheMetricMax('need_evict_cache_in_advance') != null &&
- cacheMetricMax('need_evict_cache_in_advance') == 1.0
+ cacheMetricMax('need_evict_cache_in_advance') == 0.0
}
- logger.info("Need evict cache in advance mode is now active (value =
${cacheMetricMax('need_evict_cache_in_advance')})")
- }
- awaitUntil(pollTimeoutSeconds, 1) {
- return cacheMetricMax('need_evict_cache_in_advance') != null &&
- cacheMetricMax('need_evict_cache_in_advance') == 0.0
+ return true
}
-
- return true
}
diff --git
a/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
b/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
index 72fc9950546..fadd9216fb9 100644
---
a/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
+++
b/regression-test/suites/external_table_p0/cache/test_file_cache_query_limit.groovy
@@ -48,14 +48,6 @@ suite("test_file_cache_query_limit",
"p0,external,nonConcurrent") {
return
}
- sql """set enable_file_cache=true"""
- sql """set disable_file_cache=false"""
- // The per-query file cache limit is best-effort: once a query reaches it,
BlockFileCache::try_reserve()
- // evicts only the query's own blocks that no reader holds, and admits the
new block anyway when the rest
- // are still being read. The bound asserted below holds only while few
blocks are held at once, so the
- // scans run with one scanner per instance; with up to 16 the limited
query caches well over its limit.
- sql """set max_file_scanners_concurrency=1"""
-
// Note: This test case assumes a single backend scenario. Testing with
single backend is logically equivalent
// to testing with multiple backends having identical configurations, but
simpler in logic.
// The assumption is load-bearing rather than cosmetic: the HTTP calls
below clear and inspect one backend's
@@ -72,318 +64,326 @@ suite("test_file_cache_query_limit",
"p0,external,nonConcurrent") {
// third-party docker host (hive/es/...), which in a multi-host deployment
runs no backend at all.
String beHost = aliveBackends[0].Host
- // Check backend configuration prerequisites
- def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
- logger.info("enable_file_cache configuration: " + enableFileCacheResult)
- assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
- ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-
- def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
- logger.info("file_cache_background_monitor_interval_ms configuration: " +
fileCacheBackgroundMonitorIntervalMsResult)
- assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
- fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
FILE_CACHE_BACKGROUND_MONITOR_INTERVAL_CHECK_FAILED_MSG)
-
- String catalog_name = "test_file_cache_query_limit"
- String ex_db_name = "tpch1_parquet"
- String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
- String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
- long queryCacheCapacity
- long queryLimitBytes
-
- // Sum a file_cache_statistics metric across all cache paths.
file_cache_statistics reports
- // one row per (cache_path, metric_name), so "limit 1" can observe an
arbitrary path instead
- // of the whole file cache state.
- def cacheMetricSum = { String metricName ->
- def r = sql """select sum(cast(METRIC_VALUE as double)) from
information_schema.file_cache_statistics
- where METRIC_NAME = '${metricName}';"""
- return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
- }
+ withStableFileCache {
+ // The per-query file cache limit is best-effort: once a query reaches
it, BlockFileCache::try_reserve()
+ // evicts only the query's own blocks that no reader holds, and admits
the new block anyway when the rest
+ // are still being read. The bound asserted below holds only while few
blocks are held at once, so the
+ // scans run with one scanner per instance; with up to 16 the limited
query caches well over its limit.
+ sql """set max_file_scanners_concurrency=1"""
+
+ // Check backend configuration prerequisites
+ def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
+ logger.info("enable_file_cache configuration: " +
enableFileCacheResult)
+ assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+ ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+ def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
+ logger.info("file_cache_background_monitor_interval_ms configuration:
" + fileCacheBackgroundMonitorIntervalMsResult)
+ assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
FILE_CACHE_BACKGROUND_MONITOR_INTERVAL_CHECK_FAILED_MSG)
+
+ String catalog_name = "test_file_cache_query_limit"
+ String ex_db_name = "tpch1_parquet"
+ String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+ String hms_port = context.config.otherConfigs.get(hivePrefix +
"HmsPort")
+ long queryCacheCapacity
+ long queryLimitBytes
+
+ // Sum a file_cache_statistics metric across all cache paths.
file_cache_statistics reports
+ // one row per (cache_path, metric_name), so "limit 1" can observe an
arbitrary path instead
+ // of the whole file cache state.
+ def cacheMetricSum = { String metricName ->
+ def r = sql """select sum(cast(METRIC_VALUE as double)) from
information_schema.file_cache_statistics
+ where METRIC_NAME = '${metricName}';"""
+ return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
+ }
+
+ // Poll a file_cache_statistics metric until predicate holds, or until
timeout.
+ // file_cache_statistics is refreshed by the background monitor on its
own cadence,
+ // so waiting a single fixed interval (the previous behavior) races
the refresh and
+ // makes assertions flaky. On timeout we swallow the exception so the
caller's
+ // assertFalse below can surface its own metric-specific message.
+ def pollFileCacheMetric = { String metricName, Closure predicate, long
timeoutSeconds ->
+ try {
+ Awaitility.await()
+ .atMost(timeoutSeconds, TimeUnit.SECONDS)
+ .pollInterval(1, TimeUnit.SECONDS)
+ .until {
+ Double metricValue = cacheMetricSum(metricName)
+ return metricValue != null &&
predicate(metricValue)
+ }
+ } catch (org.awaitility.core.ConditionTimeoutException ignored) {
+ // fall through; the caller's assert will surface the precise
failure
+ }
+ }
- // Poll a file_cache_statistics metric until predicate holds, or until
timeout.
- // file_cache_statistics is refreshed by the background monitor on its own
cadence,
- // so waiting a single fixed interval (the previous behavior) races the
refresh and
- // makes assertions flaky. On timeout we swallow the exception so the
caller's
- // assertFalse below can surface its own metric-specific message.
- def pollFileCacheMetric = { String metricName, Closure predicate, long
timeoutSeconds ->
- try {
+ sql """drop catalog if exists ${catalog_name} """
+
+ sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+ 'type'='hms',
+ 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+ 'hadoop.username' = 'hive'
+ );"""
+
+ String query_sql =
+ """select sum(l_quantity) as sum_qty,
+ sum(l_extendedprice) as sum_base_price,
+ sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
+ sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as
sum_charge,
+ avg(l_quantity) as avg_qty,
+ avg(l_extendedprice) as avg_price,
+ avg(l_discount) as avg_disc,
+ count(*) as count_order
+ from ${catalog_name}.${ex_db_name}.lineitem
+ where l_shipdate <= date '1998-12-01' - interval '90' day
+ group by l_returnflag, l_linestatus
+ order by l_returnflag, l_linestatus;"""
+
+ def webserverPortResult = sql """SHOW BACKEND CONFIG LIKE
'webserver_port';"""
+ logger.info("webserver_port configuration: " + webserverPortResult)
+ assertFalse(webserverPortResult.size() == 0 ||
webserverPortResult[0][3] == null || webserverPortResult[0][3].trim().isEmpty(),
+ WEB_SERVER_PORT_CHECK_FAILED_MSG)
+
+ String webserver_port = webserverPortResult[0][3]
+
+ def brpcPortResult = sql """SHOW BACKEND CONFIG LIKE 'brpc_port';"""
+ logger.info("brpcPortResult configuration: " + brpcPortResult)
+ assertFalse(brpcPortResult.size() == 0 || brpcPortResult[0][3] == null
|| brpcPortResult[0][3].trim().isEmpty(),
+ BRPC_PORT_CHECK_FAILED_MSG)
+
+ String brpc_port = brpcPortResult[0][3]
+
+ // Search file cache capacity
+ def command = ["curl", "-X", "POST", "${beHost}:${brpc_port}/vars"]
+ def stringCommand = command.collect{it.toString()}
+ def process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
+
+ def output = new StringBuilder()
+ def errorOutput = new StringBuilder()
+ process.inputStream.eachLine{line -> output.append(line).append("\n")}
+ process.errorStream.eachLine{line ->
errorOutput.append(line).append("\n")}
+
+ // Wait for process completion and check exit status
+ def exitCode = process.waitFor()
+ def fileCacheCapacityResults = output.toString().split("\n")
+ .findAll { it.contains("file_cache_capacity") }
+ .collect { it.split(":")?.last()?.trim() }
+ .findAll { it != null && !it.isEmpty() }
+ .collect { Long.valueOf(it) }
+
+ logger.info("File cache capacities: ${fileCacheCapacityResults}")
+ assertTrue(!fileCacheCapacityResults.isEmpty(), "Failed to find
file_cache_capacity in brpc metrics")
+ long fileCacheCapacity = fileCacheCapacityResults.sum() as Long
+
+ // Run file cache base test for setting the parameter
file_cache_query_limit_bytes
+ logger.info("========================= Start running file cache base
test ========================")
+
+ // Clear file cache
+ command = ["curl", "-X", "POST",
"${beHost}:${webserver_port}/api/file_cache?op=clear&sync=true"]
+ stringCommand = command.collect{it.toString()}
+ process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
+
+ output = new StringBuilder()
+ errorOutput = new StringBuilder()
+ process.inputStream.eachLine{line -> output.append(line).append("\n")}
+ process.errorStream.eachLine{line ->
errorOutput.append(line).append("\n")}
+
+ // Wait for process completion and check exit status
+ exitCode = process.waitFor()
+ logger.info("File cache clear command output: ${output.toString()}")
+ assertTrue(exitCode == 0, "File cache clear failed with exit code
${exitCode}. Error: ${errorOutput.toString()}")
+
+ // brpc metrics will be updated at most 5 seconds
+ def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toLong() / 1000) as int
+ long pollTimeoutSeconds = Math.max(30L, (long) totalWaitTime * 6L)
+
+ def waitBackendConfig = { String configName, String expectedValue ->
Awaitility.await()
- .atMost(timeoutSeconds, TimeUnit.SECONDS)
+ .atMost(pollTimeoutSeconds, TimeUnit.SECONDS)
.pollInterval(1, TimeUnit.SECONDS)
.until {
- Double metricValue = cacheMetricSum(metricName)
- return metricValue != null && predicate(metricValue)
+ def r = sql """SHOW BACKEND CONFIG LIKE
'${configName}';"""
+ return r.size() > 0 && r[0][3] != null &&
r[0][3].toString().equalsIgnoreCase(expectedValue)
}
- } catch (org.awaitility.core.ConditionTimeoutException ignored) {
- // fall through; the caller's assert will surface the precise
failure
}
- }
- sql """drop catalog if exists ${catalog_name} """
-
- sql """CREATE CATALOG ${catalog_name} PROPERTIES (
- 'type'='hms',
- 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
- 'hadoop.username' = 'hive'
- );"""
-
- String query_sql =
- """select sum(l_quantity) as sum_qty,
- sum(l_extendedprice) as sum_base_price,
- sum(l_extendedprice * (1 - l_discount)) as sum_disc_price,
- sum(l_extendedprice * (1 - l_discount) * (1 + l_tax)) as
sum_charge,
- avg(l_quantity) as avg_qty,
- avg(l_extendedprice) as avg_price,
- avg(l_discount) as avg_disc,
- count(*) as count_order
- from ${catalog_name}.${ex_db_name}.lineitem
- where l_shipdate <= date '1998-12-01' - interval '90' day
- group by l_returnflag, l_linestatus
- order by l_returnflag, l_linestatus;"""
-
- def webserverPortResult = sql """SHOW BACKEND CONFIG LIKE
'webserver_port';"""
- logger.info("webserver_port configuration: " + webserverPortResult)
- assertFalse(webserverPortResult.size() == 0 || webserverPortResult[0][3]
== null || webserverPortResult[0][3].trim().isEmpty(),
- WEB_SERVER_PORT_CHECK_FAILED_MSG)
-
- String webserver_port = webserverPortResult[0][3]
-
- def brpcPortResult = sql """SHOW BACKEND CONFIG LIKE 'brpc_port';"""
- logger.info("brpcPortResult configuration: " + brpcPortResult)
- assertFalse(brpcPortResult.size() == 0 || brpcPortResult[0][3] == null ||
brpcPortResult[0][3].trim().isEmpty(),
- BRPC_PORT_CHECK_FAILED_MSG)
-
- String brpc_port = brpcPortResult[0][3]
-
- // Search file cache capacity
- def command = ["curl", "-X", "POST", "${beHost}:${brpc_port}/vars"]
- def stringCommand = command.collect{it.toString()}
- def process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
-
- def output = new StringBuilder()
- def errorOutput = new StringBuilder()
- process.inputStream.eachLine{line -> output.append(line).append("\n")}
- process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
- // Wait for process completion and check exit status
- def exitCode = process.waitFor()
- def fileCacheCapacityResults = output.toString().split("\n")
- .findAll { it.contains("file_cache_capacity") }
- .collect { it.split(":")?.last()?.trim() }
- .findAll { it != null && !it.isEmpty() }
- .collect { Long.valueOf(it) }
-
- logger.info("File cache capacities: ${fileCacheCapacityResults}")
- assertTrue(!fileCacheCapacityResults.isEmpty(), "Failed to find
file_cache_capacity in brpc metrics")
- long fileCacheCapacity = fileCacheCapacityResults.sum() as Long
-
- // Run file cache base test for setting the parameter
file_cache_query_limit_bytes
- logger.info("========================= Start running file cache base test
========================")
-
- // Clear file cache
- command = ["curl", "-X", "POST",
"${beHost}:${webserver_port}/api/file_cache?op=clear&sync=true"]
- stringCommand = command.collect{it.toString()}
- process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
-
- output = new StringBuilder()
- errorOutput = new StringBuilder()
- process.inputStream.eachLine{line -> output.append(line).append("\n")}
- process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
- // Wait for process completion and check exit status
- exitCode = process.waitFor()
- logger.info("File cache clear command output: ${output.toString()}")
- assertTrue(exitCode == 0, "File cache clear failed with exit code
${exitCode}. Error: ${errorOutput.toString()}")
-
- // brpc metrics will be updated at most 5 seconds
- def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toLong() / 1000) as int
- long pollTimeoutSeconds = Math.max(30L, (long) totalWaitTime * 6L)
-
- def waitBackendConfig = { String configName, String expectedValue ->
- Awaitility.await()
- .atMost(pollTimeoutSeconds, TimeUnit.SECONDS)
- .pollInterval(1, TimeUnit.SECONDS)
- .until {
- def r = sql """SHOW BACKEND CONFIG LIKE '${configName}';"""
- return r.size() > 0 && r[0][3] != null &&
r[0][3].toString().equalsIgnoreCase(expectedValue)
- }
- }
+ // Poll until the cache clear has drained the LRU queue. The HTTP
clear endpoint with sync=true
+ // deletes blocks synchronously, but the queue counters are
republished by the background monitor
+ // thread on its own cadence — so a single fixed-time wait can race
the refresh.
+ pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 },
pollTimeoutSeconds)
+ pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 },
pollTimeoutSeconds)
- // Poll until the cache clear has drained the LRU queue. The HTTP clear
endpoint with sync=true
- // deletes blocks synchronously, but the queue counters are republished by
the background monitor
- // thread on its own cadence — so a single fixed-time wait can race the
refresh.
- pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 },
pollTimeoutSeconds)
- pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 },
pollTimeoutSeconds)
-
- Double initialNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
- logger.info("normal_queue_curr_size sum result: " +
initialNormalQueueCurrSize)
- assertFalse(initialNormalQueueCurrSize == null ||
initialNormalQueueCurrSize != 0.0,
- INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
-
- Double initialNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
- logger.info("normal_queue_curr_elements sum result: " +
initialNormalQueueCurrElements)
- assertFalse(initialNormalQueueCurrElements == null ||
initialNormalQueueCurrElements != 0.0,
- INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
-
- logger.info("Initial normal queue curr size and elements - size:
${initialNormalQueueCurrSize} , " +
- "elements: ${initialNormalQueueCurrElements}")
-
- setBeConfigTemporary([
- "enable_file_cache_query_limit": "false"
- ]) {
- // Execute test logic with modified configuration for
file_cache_query_limit
- logger.info("Backend configuration set -
enable_file_cache_query_limit: false")
-
- waitBackendConfig("enable_file_cache_query_limit", "false")
-
- // Check if the configuration is modified
- def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG LIKE
'enable_file_cache_query_limit';"""
- logger.info("enable_file_cache_query_limit configuration: " +
enableFileCacheQueryLimitResult)
- assertFalse(enableFileCacheQueryLimitResult.size() == 0 ||
enableFileCacheQueryLimitResult[0][3] == null ||
enableFileCacheQueryLimitResult[0][3] != "false",
- ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_FALSE_FAILED_MSG)
-
- sql """switch ${catalog_name}"""
- // load the table into file cache
- sql query_sql
-
- // Poll until the query has populated the cache.
- pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 },
pollTimeoutSeconds)
- pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 },
pollTimeoutSeconds)
-
- Double baseNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
- logger.info("normal_queue_curr_elements sum result: " +
baseNormalQueueCurrElements)
- assertFalse(baseNormalQueueCurrElements == null ||
baseNormalQueueCurrElements == 0.0,
- BASE_NORMAL_QUEUE_CURR_ELEMENTS_IS_ZERO_MSG)
-
- Double baseNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
- logger.info("normal_queue_curr_size sum result: " +
baseNormalQueueCurrSize)
- assertFalse(baseNormalQueueCurrSize == null || baseNormalQueueCurrSize
== 0.0,
- BASE_NORMAL_QUEUE_CURR_SIZE_IS_ZERO_MSG)
-
- queryCacheCapacity = baseNormalQueueCurrSize as Long
- }
+ Double initialNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
+ logger.info("normal_queue_curr_size sum result: " +
initialNormalQueueCurrSize)
+ assertFalse(initialNormalQueueCurrSize == null ||
initialNormalQueueCurrSize != 0.0,
+ INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
- // The parameter file_cache_query_limit_percent must be set smaller than
the cache capacity required by the query
- def fileCacheQueryLimitPercent = (queryCacheCapacity / fileCacheCapacity)
* 100
- logger.info("file_cache_query_limit_percent: " +
fileCacheQueryLimitPercent)
-
- logger.info("========================== End running file cache base test
=========================")
-
- logger.info("==================== Start running file cache query limit
test 1 ====================")
-
- long fileCacheQueryLimitPercentTest1 = Math.max(1L,
(fileCacheQueryLimitPercent / 2) as Long)
- queryLimitBytes = (fileCacheCapacity * fileCacheQueryLimitPercentTest1 /
100) as Long
- logger.info("file_cache_query_limit_percent_test1: " +
fileCacheQueryLimitPercentTest1)
- logger.info("query_limit_bytes: ${queryLimitBytes}, query_cache_capacity:
${queryCacheCapacity}")
- assertTrue(queryLimitBytes > 0 && queryLimitBytes < queryCacheCapacity,
- FILE_CACHE_QUERY_LIMIT_BYTES_CHECK_FAILED_MSG)
-
- // Clear file cache
- process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
-
- output = new StringBuilder()
- errorOutput = new StringBuilder()
- process.inputStream.eachLine{line -> output.append(line).append("\n")}
- process.errorStream.eachLine{line -> errorOutput.append(line).append("\n")}
-
- // Wait for process completion and check exit status
- exitCode = process.waitFor()
- logger.info("File cache clear command output: ${output.toString()}")
- assertTrue(exitCode == 0, "File cache clear failed with exit code
${exitCode}. Error: ${errorOutput.toString()}")
-
- // Poll until the file cache is fully cleared again.
- pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 },
pollTimeoutSeconds)
- pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 },
pollTimeoutSeconds)
-
- // ===== Normal Queue Metrics Check =====
- // Check normal queue current size
- initialNormalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
- logger.info("normal_queue_curr_size sum result: " +
initialNormalQueueCurrSize)
- assertFalse(initialNormalQueueCurrSize == null ||
initialNormalQueueCurrSize != 0.0,
- INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
-
- // Check normal queue current elements
- initialNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
- logger.info("normal_queue_curr_elements sum result: " +
initialNormalQueueCurrElements)
- assertFalse(initialNormalQueueCurrElements == null ||
initialNormalQueueCurrElements != 0.0,
- INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
-
- // Check normal queue max size
- Double initialNormalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
- logger.info("normal_queue_max_size sum result: " +
initialNormalQueueMaxSize)
- assertFalse(initialNormalQueueMaxSize == null || initialNormalQueueMaxSize
== 0.0,
- INITIAL_NORMAL_QUEUE_MAX_SIZE_IS_ZERO_MSG)
-
- // Check normal queue max elements
- Double initialNormalQueueMaxElements =
cacheMetricSum('normal_queue_max_elements')
- logger.info("normal_queue_max_elements sum result: " +
initialNormalQueueMaxElements)
- assertFalse(initialNormalQueueMaxElements == null ||
initialNormalQueueMaxElements == 0.0,
- INITIAL_NORMAL_QUEUE_MAX_ELEMENTS_IS_ZERO_MSG)
-
- logger.info("Initial normal queue curr size and elements - size:
${initialNormalQueueCurrSize} , " +
+ Double initialNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+ logger.info("normal_queue_curr_elements sum result: " +
initialNormalQueueCurrElements)
+ assertFalse(initialNormalQueueCurrElements == null ||
initialNormalQueueCurrElements != 0.0,
+ INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
+
+ logger.info("Initial normal queue curr size and elements - size:
${initialNormalQueueCurrSize} , " +
"elements: ${initialNormalQueueCurrElements}")
- logger.info("Initial normal queue max size and elements - size:
${initialNormalQueueMaxSize} , " +
- "elements: ${initialNormalQueueMaxElements}")
+ setBeConfigTemporary([
+ "enable_file_cache_query_limit": "false"
+ ]) {
+ // Execute test logic with modified configuration for
file_cache_query_limit
+ logger.info("Backend configuration set -
enable_file_cache_query_limit: false")
+
+ waitBackendConfig("enable_file_cache_query_limit", "false")
- // ===== Hit And Read Counts Metrics Check =====
- // total_hit_counts / total_read_counts are also reported per cache path.
- Double initialTotalHitCounts = cacheMetricSum('total_hit_counts')
- Double initialTotalReadCounts = cacheMetricSum('total_read_counts')
- logger.info("Initial total_hit_counts (sum): ${initialTotalHitCounts},
total_read_counts (sum): ${initialTotalReadCounts}")
+ // Check if the configuration is modified
+ def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG
LIKE 'enable_file_cache_query_limit';"""
+ logger.info("enable_file_cache_query_limit configuration: " +
enableFileCacheQueryLimitResult)
+ assertFalse(enableFileCacheQueryLimitResult.size() == 0 ||
enableFileCacheQueryLimitResult[0][3] == null ||
enableFileCacheQueryLimitResult[0][3] != "false",
+ ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_FALSE_FAILED_MSG)
- // Set backend configuration parameters for file_cache_query_limit test 1
- setBeConfigTemporary([
- "enable_file_cache_query_limit": "true"
- ]) {
- // Execute test logic with modified configuration for
file_cache_query_limit
- logger.info("Backend configuration set -
enable_file_cache_query_limit: true")
+ sql """switch ${catalog_name}"""
+ // load the table into file cache
+ sql query_sql
- sql """set file_cache_query_limit_percent =
${fileCacheQueryLimitPercentTest1}"""
+ // Poll until the query has populated the cache.
+ pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 },
pollTimeoutSeconds)
+ pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 },
pollTimeoutSeconds)
- waitBackendConfig("enable_file_cache_query_limit", "true")
+ Double baseNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+ logger.info("normal_queue_curr_elements sum result: " +
baseNormalQueueCurrElements)
+ assertFalse(baseNormalQueueCurrElements == null ||
baseNormalQueueCurrElements == 0.0,
+ BASE_NORMAL_QUEUE_CURR_ELEMENTS_IS_ZERO_MSG)
- // Check if the configuration is modified
- def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG LIKE
'enable_file_cache_query_limit';"""
- logger.info("enable_file_cache_query_limit configuration: " +
enableFileCacheQueryLimitResult)
- assertFalse(enableFileCacheQueryLimitResult.size() == 0 ||
enableFileCacheQueryLimitResult[0][3] == null ||
enableFileCacheQueryLimitResult[0][3] != "true",
- ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_TRUE_FAILED_MSG)
+ Double baseNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
+ logger.info("normal_queue_curr_size sum result: " +
baseNormalQueueCurrSize)
+ assertFalse(baseNormalQueueCurrSize == null ||
baseNormalQueueCurrSize == 0.0,
+ BASE_NORMAL_QUEUE_CURR_SIZE_IS_ZERO_MSG)
- sql """switch ${catalog_name}"""
+ queryCacheCapacity = baseNormalQueueCurrSize as Long
+ }
- // load the table into file cache
- sql query_sql
+ // The parameter file_cache_query_limit_percent must be set smaller
than the cache capacity required by the query
+ def fileCacheQueryLimitPercent = (queryCacheCapacity /
fileCacheCapacity) * 100
+ logger.info("file_cache_query_limit_percent: " +
fileCacheQueryLimitPercent)
+
+ logger.info("========================== End running file cache base
test =========================")
- // Poll until the query has populated the cache under the new
file_cache_query_limit.
- pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 },
pollTimeoutSeconds)
- pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 },
pollTimeoutSeconds)
+ logger.info("==================== Start running file cache query limit
test 1 ====================")
+
+ long fileCacheQueryLimitPercentTest1 = Math.max(1L,
(fileCacheQueryLimitPercent / 2) as Long)
+ queryLimitBytes = (fileCacheCapacity * fileCacheQueryLimitPercentTest1
/ 100) as Long
+ logger.info("file_cache_query_limit_percent_test1: " +
fileCacheQueryLimitPercentTest1)
+ logger.info("query_limit_bytes: ${queryLimitBytes},
query_cache_capacity: ${queryCacheCapacity}")
+ assertTrue(queryLimitBytes > 0 && queryLimitBytes < queryCacheCapacity,
+ FILE_CACHE_QUERY_LIMIT_BYTES_CHECK_FAILED_MSG)
- // Get updated value of normal queue current elements and max elements
after cache operations
- // Check if updated values are greater than initial values
- Double updatedNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
- Double updatedNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+ // Clear file cache
+ process = new ProcessBuilder(stringCommand as
String[]).redirectErrorStream(true).start()
- logger.info("Updated normal queue curr size and elements sum - size:
${updatedNormalQueueCurrSize} , " +
- "elements: ${updatedNormalQueueCurrElements}")
+ output = new StringBuilder()
+ errorOutput = new StringBuilder()
+ process.inputStream.eachLine{line -> output.append(line).append("\n")}
+ process.errorStream.eachLine{line ->
errorOutput.append(line).append("\n")}
- assertTrue(updatedNormalQueueCurrSize > 0.0,
NORMAL_QUEUE_CURR_SIZE_NOT_GREATER_THAN_ZERO_MSG)
- assertTrue(updatedNormalQueueCurrElements > 0.0,
NORMAL_QUEUE_CURR_ELEMENTS_NOT_GREATER_THAN_ZERO_MSG)
+ // Wait for process completion and check exit status
+ exitCode = process.waitFor()
+ logger.info("File cache clear command output: ${output.toString()}")
+ assertTrue(exitCode == 0, "File cache clear failed with exit code
${exitCode}. Error: ${errorOutput.toString()}")
- logger.info("Normal queue curr size and query cache limit comparison -
normal queue curr size: ${updatedNormalQueueCurrSize as Long} , " +
- "query cache limit: ${queryLimitBytes}, baseline query cache
capacity: ${queryCacheCapacity}")
+ // Poll until the file cache is fully cleared again.
+ pollFileCacheMetric('normal_queue_curr_size', { it == 0.0 },
pollTimeoutSeconds)
+ pollFileCacheMetric('normal_queue_curr_elements', { it == 0.0 },
pollTimeoutSeconds)
- assertTrue((updatedNormalQueueCurrSize as Long) <= queryLimitBytes,
- NORMAL_QUEUE_CURR_SIZE_GREATER_THAN_QUERY_CACHE_LIMIT_MSG)
+ // ===== Normal Queue Metrics Check =====
+ // Check normal queue current size
+ initialNormalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
+ logger.info("normal_queue_curr_size sum result: " +
initialNormalQueueCurrSize)
+ assertFalse(initialNormalQueueCurrSize == null ||
initialNormalQueueCurrSize != 0.0,
+ INITIAL_NORMAL_QUEUE_CURR_SIZE_NOT_ZERO_MSG)
- Double updatedTotalHitCounts = cacheMetricSum('total_hit_counts')
- Double updatedTotalReadCounts = cacheMetricSum('total_read_counts')
+ // Check normal queue current elements
+ initialNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+ logger.info("normal_queue_curr_elements sum result: " +
initialNormalQueueCurrElements)
+ assertFalse(initialNormalQueueCurrElements == null ||
initialNormalQueueCurrElements != 0.0,
+ INITIAL_NORMAL_QUEUE_CURR_ELEMENTS_NOT_ZERO_MSG)
- logger.info("Total hit and read counts comparison - hit counts:
${initialTotalHitCounts} -> " +
- "${updatedTotalHitCounts} , read counts:
${initialTotalReadCounts} -> ${updatedTotalReadCounts}")
+ // Check normal queue max size
+ Double initialNormalQueueMaxSize =
cacheMetricSum('normal_queue_max_size')
+ logger.info("normal_queue_max_size sum result: " +
initialNormalQueueMaxSize)
+ assertFalse(initialNormalQueueMaxSize == null ||
initialNormalQueueMaxSize == 0.0,
+ INITIAL_NORMAL_QUEUE_MAX_SIZE_IS_ZERO_MSG)
- assertTrue(updatedTotalReadCounts > initialTotalReadCounts,
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
- }
+ // Check normal queue max elements
+ Double initialNormalQueueMaxElements =
cacheMetricSum('normal_queue_max_elements')
+ logger.info("normal_queue_max_elements sum result: " +
initialNormalQueueMaxElements)
+ assertFalse(initialNormalQueueMaxElements == null ||
initialNormalQueueMaxElements == 0.0,
+ INITIAL_NORMAL_QUEUE_MAX_ELEMENTS_IS_ZERO_MSG)
+
+ logger.info("Initial normal queue curr size and elements - size:
${initialNormalQueueCurrSize} , " +
+ "elements: ${initialNormalQueueCurrElements}")
+
+ logger.info("Initial normal queue max size and elements - size:
${initialNormalQueueMaxSize} , " +
+ "elements: ${initialNormalQueueMaxElements}")
+
+ // ===== Hit And Read Counts Metrics Check =====
+ // total_hit_counts / total_read_counts are also reported per cache
path.
+ Double initialTotalHitCounts = cacheMetricSum('total_hit_counts')
+ Double initialTotalReadCounts = cacheMetricSum('total_read_counts')
+ logger.info("Initial total_hit_counts (sum): ${initialTotalHitCounts},
total_read_counts (sum): ${initialTotalReadCounts}")
- logger.info("===================== End running file cache query limit test
1 =====================")
+ // Set backend configuration parameters for file_cache_query_limit
test 1
+ setBeConfigTemporary([
+ "enable_file_cache_query_limit": "true"
+ ]) {
+ // Execute test logic with modified configuration for
file_cache_query_limit
+ logger.info("Backend configuration set -
enable_file_cache_query_limit: true")
- return true;
+ sql """set file_cache_query_limit_percent =
${fileCacheQueryLimitPercentTest1}"""
+
+ waitBackendConfig("enable_file_cache_query_limit", "true")
+
+ // Check if the configuration is modified
+ def enableFileCacheQueryLimitResult = sql """SHOW BACKEND CONFIG
LIKE 'enable_file_cache_query_limit';"""
+ logger.info("enable_file_cache_query_limit configuration: " +
enableFileCacheQueryLimitResult)
+ assertFalse(enableFileCacheQueryLimitResult.size() == 0 ||
enableFileCacheQueryLimitResult[0][3] == null ||
enableFileCacheQueryLimitResult[0][3] != "true",
+ ENABLE_FILE_CACHE_QUERY_LIMIT_CHECK_TRUE_FAILED_MSG)
+
+ sql """switch ${catalog_name}"""
+
+ // load the table into file cache
+ sql query_sql
+
+ // Poll until the query has populated the cache under the new
file_cache_query_limit.
+ pollFileCacheMetric('normal_queue_curr_size', { it > 0.0 },
pollTimeoutSeconds)
+ pollFileCacheMetric('normal_queue_curr_elements', { it > 0.0 },
pollTimeoutSeconds)
+
+ // Get updated value of normal queue current elements and max
elements after cache operations
+ // Check if updated values are greater than initial values
+ Double updatedNormalQueueCurrSize =
cacheMetricSum('normal_queue_curr_size')
+ Double updatedNormalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+
+ logger.info("Updated normal queue curr size and elements sum -
size: ${updatedNormalQueueCurrSize} , " +
+ "elements: ${updatedNormalQueueCurrElements}")
+
+ assertTrue(updatedNormalQueueCurrSize > 0.0,
NORMAL_QUEUE_CURR_SIZE_NOT_GREATER_THAN_ZERO_MSG)
+ assertTrue(updatedNormalQueueCurrElements > 0.0,
NORMAL_QUEUE_CURR_ELEMENTS_NOT_GREATER_THAN_ZERO_MSG)
+
+ logger.info("Normal queue curr size and query cache limit
comparison - normal queue curr size: ${updatedNormalQueueCurrSize as Long} , " +
+ "query cache limit: ${queryLimitBytes}, baseline query
cache capacity: ${queryCacheCapacity}")
+
+ assertTrue((updatedNormalQueueCurrSize as Long) <= queryLimitBytes,
+ NORMAL_QUEUE_CURR_SIZE_GREATER_THAN_QUERY_CACHE_LIMIT_MSG)
+
+ Double updatedTotalHitCounts = cacheMetricSum('total_hit_counts')
+ Double updatedTotalReadCounts = cacheMetricSum('total_read_counts')
+
+ logger.info("Total hit and read counts comparison - hit counts:
${initialTotalHitCounts} -> " +
+ "${updatedTotalHitCounts} , read counts:
${initialTotalReadCounts} -> ${updatedTotalReadCounts}")
+
+ assertTrue(updatedTotalReadCounts > initialTotalReadCounts,
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
+ }
+
+ logger.info("===================== End running file cache query limit
test 1 =====================")
+
+ return true;
+ }
}
diff --git
a/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
b/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
index 4c4468dadda..64413bb11a4 100644
---
a/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
+++
b/regression-test/suites/external_table_p0/cache/test_file_cache_statistics.groovy
@@ -43,129 +43,125 @@ suite("test_file_cache_statistics",
"p0,external,nonConcurrent") {
return;
}
- sql """set enable_file_cache=true"""
- sql """set disable_file_cache=false"""
- // This case validates BlockFileCache counters. Keep upper-layer caches
and scan scheduling
- // from serving or cancelling the repeated read before it reaches
BlockFileCache.
- sql """set enable_sql_cache=false"""
- sql """set enable_hive_sql_cache=false"""
- sql """set enable_parquet_file_page_cache=false"""
- sql """set parallel_pipeline_task_num=1"""
-
- // Check backend configuration prerequisites
- // Note: This test case assumes a single backend scenario. Testing with
single backend is logically equivalent
- // to testing with multiple backends having identical configurations, but
simpler in logic.
- def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
- logger.info("enable_file_cache configuration: " + enableFileCacheResult)
- assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
- ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
-
- def fileCachePathResult = sql """show backend config like
'file_cache_path';"""
- logger.info("file_cache_path configuration: " + fileCachePathResult)
- assertFalse(fileCachePathResult.size() == 0 || fileCachePathResult[0][3]
== null || fileCachePathResult[0][3].trim().isEmpty(),
- FILE_CACHE_PATH_CHECK_FAILED_MSG)
-
- String catalog_name = "test_file_cache_statistics"
- String ex_db_name = "`default`"
- String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
- String hms_port = context.config.otherConfigs.get(hivePrefix + "HmsPort")
-
- def cacheMetric = { String metricName, String aggregateFunc ->
- def r = sql """select ${aggregateFunc}(cast(METRIC_VALUE as double))
from information_schema.file_cache_statistics
- where METRIC_NAME = '${metricName}';"""
- return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
- }
- def cacheMetricSum = { String metricName -> cacheMetric(metricName, "sum")
}
- def cacheMetricMax = { String metricName -> cacheMetric(metricName, "max")
}
-
- sql """drop catalog if exists ${catalog_name} """
-
- sql """CREATE CATALOG ${catalog_name} PROPERTIES (
- 'type'='hms',
- 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
- 'hadoop.username' = 'hive'
- );"""
-
- sql """switch ${catalog_name}"""
-
- // Pin the query to one partition file instead of racing all six file scan
ranges under LIMIT 1.
- String querySql = """select * from
${catalog_name}.${ex_db_name}.parquet_partition_table
- where nation='cn' and city='beijing'
- and l_orderkey=1 and l_partkey=1534 limit 1;"""
-
- // load the table into file cache
- sql querySql
- // do it twice to make sure the table block could hit the cache
- order_qt_1 querySql
-
- def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
- logger.info("file_cache_background_monitor_interval_ms configuration: " +
fileCacheBackgroundMonitorIntervalMsResult)
- assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
- fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
"file_cache_background_monitor_interval_ms is empty or not set to true")
-
- def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
- int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
-
- awaitUntil(pollTimeoutSeconds, 1) {
- return cacheMetricMax('hits_ratio') != null &&
cacheMetricMax('hits_ratio') > 0.0 &&
- cacheMetricMax('hits_ratio_1h') != null &&
cacheMetricMax('hits_ratio_1h') > 0.0 &&
- cacheMetricMax('hits_ratio_5m') != null &&
cacheMetricMax('hits_ratio_5m') > 0.0 &&
- cacheMetricSum('normal_queue_curr_size') != null &&
cacheMetricSum('normal_queue_curr_size') > 0.0 &&
- cacheMetricSum('normal_queue_max_size') != null &&
cacheMetricSum('normal_queue_max_size') > 0.0 &&
- cacheMetricSum('normal_queue_curr_elements') != null &&
cacheMetricSum('normal_queue_curr_elements') > 0.0 &&
- cacheMetricSum('normal_queue_max_elements') != null &&
cacheMetricSum('normal_queue_max_elements') > 0.0 &&
- cacheMetricSum('total_hit_counts') != null &&
cacheMetricSum('total_hit_counts') > 0.0 &&
- cacheMetricSum('total_read_counts') != null &&
cacheMetricSum('total_read_counts') > 0.0
- }
+ withStableFileCache {
+ // Keep LIMIT cancellation from racing the single partition file being
measured.
+ sql """set parallel_pipeline_task_num=1"""
+
+ // Check backend configuration prerequisites
+ // Note: This test case assumes a single backend scenario. Testing
with single backend is logically equivalent
+ // to testing with multiple backends having identical configurations,
but simpler in logic.
+ def enableFileCacheResult = sql """show backend config like
'enable_file_cache';"""
+ logger.info("enable_file_cache configuration: " +
enableFileCacheResult)
+ assertFalse(enableFileCacheResult.size() == 0 ||
!enableFileCacheResult[0][3].equalsIgnoreCase("true"),
+ ENABLE_FILE_CACHE_CHECK_FAILED_MSG)
+
+ def fileCachePathResult = sql """show backend config like
'file_cache_path';"""
+ logger.info("file_cache_path configuration: " + fileCachePathResult)
+ assertFalse(fileCachePathResult.size() == 0 ||
fileCachePathResult[0][3] == null || fileCachePathResult[0][3].trim().isEmpty(),
+ FILE_CACHE_PATH_CHECK_FAILED_MSG)
+
+ String catalog_name = "test_file_cache_statistics"
+ String ex_db_name = "`default`"
+ String externalEnvIp = context.config.otherConfigs.get("externalEnvIp")
+ String hms_port = context.config.otherConfigs.get(hivePrefix +
"HmsPort")
+
+ def cacheMetric = { String metricName, String aggregateFunc ->
+ def r = sql """select ${aggregateFunc}(cast(METRIC_VALUE as
double)) from information_schema.file_cache_statistics
+ where METRIC_NAME = '${metricName}';"""
+ return (r.size() == 0 || r[0][0] == null) ? null :
Double.valueOf(r[0][0].toString())
+ }
+ def cacheMetricSum = { String metricName -> cacheMetric(metricName,
"sum") }
+ def cacheMetricMax = { String metricName -> cacheMetric(metricName,
"max") }
+
+ sql """drop catalog if exists ${catalog_name} """
+
+ sql """CREATE CATALOG ${catalog_name} PROPERTIES (
+ 'type'='hms',
+ 'hive.metastore.uris' = 'thrift://${externalEnvIp}:${hms_port}',
+ 'hadoop.username' = 'hive'
+ );"""
+
+ sql """switch ${catalog_name}"""
+
+ // Pin the query to one partition file instead of racing all six file
scan ranges under LIMIT 1.
+ String querySql = """select * from
${catalog_name}.${ex_db_name}.parquet_partition_table
+ where nation='cn' and city='beijing'
+ and l_orderkey=1 and l_partkey=1534 limit 1;"""
+
+ // load the table into file cache
+ sql querySql
+ // do it twice to make sure the table block could hit the cache
+ order_qt_1 querySql
+
+ def fileCacheBackgroundMonitorIntervalMsResult = sql """show backend
config like 'file_cache_background_monitor_interval_ms';"""
+ logger.info("file_cache_background_monitor_interval_ms configuration:
" + fileCacheBackgroundMonitorIntervalMsResult)
+ assertFalse(fileCacheBackgroundMonitorIntervalMsResult.size() == 0 ||
fileCacheBackgroundMonitorIntervalMsResult[0][3] == null ||
+
fileCacheBackgroundMonitorIntervalMsResult[0][3].trim().isEmpty(),
"file_cache_background_monitor_interval_ms is empty or not set to true")
+
+ def totalWaitTime =
(fileCacheBackgroundMonitorIntervalMsResult[0][3].toInteger() / 1000) as int
+ int pollTimeoutSeconds = Math.max(30, totalWaitTime * 6)
+
+ awaitUntil(pollTimeoutSeconds, 1) {
+ return cacheMetricMax('hits_ratio') != null &&
cacheMetricMax('hits_ratio') > 0.0 &&
+ cacheMetricMax('hits_ratio_1h') != null &&
cacheMetricMax('hits_ratio_1h') > 0.0 &&
+ cacheMetricMax('hits_ratio_5m') != null &&
cacheMetricMax('hits_ratio_5m') > 0.0 &&
+ cacheMetricSum('normal_queue_curr_size') != null &&
cacheMetricSum('normal_queue_curr_size') > 0.0 &&
+ cacheMetricSum('normal_queue_max_size') != null &&
cacheMetricSum('normal_queue_max_size') > 0.0 &&
+ cacheMetricSum('normal_queue_curr_elements') != null &&
cacheMetricSum('normal_queue_curr_elements') > 0.0 &&
+ cacheMetricSum('normal_queue_max_elements') != null &&
cacheMetricSum('normal_queue_max_elements') > 0.0 &&
+ cacheMetricSum('total_hit_counts') != null &&
cacheMetricSum('total_hit_counts') > 0.0 &&
+ cacheMetricSum('total_read_counts') != null &&
cacheMetricSum('total_read_counts') > 0.0
+ }
+
+ Double hitsRatio = cacheMetricMax('hits_ratio')
+ Double hitsRatio1h = cacheMetricMax('hits_ratio_1h')
+ Double hitsRatio5m = cacheMetricMax('hits_ratio_5m')
+ logger.info("Hit ratio metrics - hits_ratio: ${hitsRatio},
hits_ratio_1h: ${hitsRatio1h}, hits_ratio_5m: ${hitsRatio5m}")
+ assertTrue(hitsRatio > 0.0, HIT_RATIO_METRIC_FALSE_MSG)
+ assertTrue(hitsRatio1h > 0.0, HIT_RATIO_1H_METRIC_FALSE_MSG)
+ assertTrue(hitsRatio5m > 0.0, HIT_RATIO_5M_METRIC_FALSE_MSG)
+
+ Double normalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
+ Double normalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
+ Double normalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
+ Double normalQueueMaxElements =
cacheMetricSum('normal_queue_max_elements')
+ Double indexQueueMaxSize = cacheMetricSum('index_queue_max_size')
+ Double ttlQueueMaxSize = cacheMetricSum('ttl_queue_max_size')
+ Double disposableQueueMaxSize =
cacheMetricSum('disposable_queue_max_size')
+ Double cacheCapacity = (normalQueueMaxSize == null ||
indexQueueMaxSize == null ||
+ ttlQueueMaxSize == null || disposableQueueMaxSize == null) ?
null :
+ normalQueueMaxSize + indexQueueMaxSize + ttlQueueMaxSize +
disposableQueueMaxSize
+ logger.info("Normal queue metrics - curr_size: ${normalQueueCurrSize},
max_size: ${normalQueueMaxSize}, " +
+ "curr_elements: ${normalQueueCurrElements}, max_elements:
${normalQueueMaxElements}")
+ logger.info("Total file cache capacity: ${cacheCapacity}")
+ // A queue's max_size is a soft limit. A queue may borrow unused
capacity from
+ // other queues, while the total cache capacity remains the hard upper
bound.
+ assertTrue(normalQueueCurrSize > 0.0 && cacheCapacity != null &&
normalQueueCurrSize <= cacheCapacity,
+ NORMAL_QUEUE_SIZE_VALIDATION_FAILED_MSG)
+ assertTrue(normalQueueCurrElements > 0.0,
NORMAL_QUEUE_ELEMENTS_VALIDATION_FAILED_MSG)
+
+ Double initialHitCounts = cacheMetricSum('total_hit_counts')
+ Double initialReadCounts = cacheMetricSum('total_read_counts')
+ logger.info("Initial hit/read counts - hit_counts:
${initialHitCounts}, read_counts: ${initialReadCounts}")
+
+ // Execute the same query to trigger cache operations
+ order_qt_2 querySql
+
+ awaitUntil(pollTimeoutSeconds, 1) {
+ Double updatedHitCounts = cacheMetricSum('total_hit_counts')
+ Double updatedReadCounts = cacheMetricSum('total_read_counts')
+ return updatedHitCounts != null && updatedHitCounts >
initialHitCounts &&
+ updatedReadCounts != null && updatedReadCounts >
initialReadCounts
+ }
- Double hitsRatio = cacheMetricMax('hits_ratio')
- Double hitsRatio1h = cacheMetricMax('hits_ratio_1h')
- Double hitsRatio5m = cacheMetricMax('hits_ratio_5m')
- logger.info("Hit ratio metrics - hits_ratio: ${hitsRatio}, hits_ratio_1h:
${hitsRatio1h}, hits_ratio_5m: ${hitsRatio5m}")
- assertTrue(hitsRatio > 0.0, HIT_RATIO_METRIC_FALSE_MSG)
- assertTrue(hitsRatio1h > 0.0, HIT_RATIO_1H_METRIC_FALSE_MSG)
- assertTrue(hitsRatio5m > 0.0, HIT_RATIO_5M_METRIC_FALSE_MSG)
-
- Double normalQueueCurrSize = cacheMetricSum('normal_queue_curr_size')
- Double normalQueueMaxSize = cacheMetricSum('normal_queue_max_size')
- Double normalQueueCurrElements =
cacheMetricSum('normal_queue_curr_elements')
- Double normalQueueMaxElements = cacheMetricSum('normal_queue_max_elements')
- Double indexQueueMaxSize = cacheMetricSum('index_queue_max_size')
- Double ttlQueueMaxSize = cacheMetricSum('ttl_queue_max_size')
- Double disposableQueueMaxSize = cacheMetricSum('disposable_queue_max_size')
- Double cacheCapacity = (normalQueueMaxSize == null || indexQueueMaxSize ==
null ||
- ttlQueueMaxSize == null || disposableQueueMaxSize == null) ? null :
- normalQueueMaxSize + indexQueueMaxSize + ttlQueueMaxSize +
disposableQueueMaxSize
- logger.info("Normal queue metrics - curr_size: ${normalQueueCurrSize},
max_size: ${normalQueueMaxSize}, " +
- "curr_elements: ${normalQueueCurrElements}, max_elements:
${normalQueueMaxElements}")
- logger.info("Total file cache capacity: ${cacheCapacity}")
- // A queue's max_size is a soft limit. A queue may borrow unused capacity
from
- // other queues, while the total cache capacity remains the hard upper
bound.
- assertTrue(normalQueueCurrSize > 0.0 && cacheCapacity != null &&
normalQueueCurrSize <= cacheCapacity,
- NORMAL_QUEUE_SIZE_VALIDATION_FAILED_MSG)
- assertTrue(normalQueueCurrElements > 0.0,
NORMAL_QUEUE_ELEMENTS_VALIDATION_FAILED_MSG)
-
- Double initialHitCounts = cacheMetricSum('total_hit_counts')
- Double initialReadCounts = cacheMetricSum('total_read_counts')
- logger.info("Initial hit/read counts - hit_counts: ${initialHitCounts},
read_counts: ${initialReadCounts}")
-
- // Execute the same query to trigger cache operations
- order_qt_2 querySql
-
- awaitUntil(pollTimeoutSeconds, 1) {
Double updatedHitCounts = cacheMetricSum('total_hit_counts')
Double updatedReadCounts = cacheMetricSum('total_read_counts')
- return updatedHitCounts != null && updatedHitCounts > initialHitCounts
&&
- updatedReadCounts != null && updatedReadCounts >
initialReadCounts
- }
- Double updatedHitCounts = cacheMetricSum('total_hit_counts')
- Double updatedReadCounts = cacheMetricSum('total_read_counts')
+ logger.info("Hit and read counts comparison - hit_counts:
${initialHitCounts} -> " +
+ "${updatedHitCounts}, read_counts: ${initialReadCounts} ->
${updatedReadCounts}")
- logger.info("Hit and read counts comparison - hit_counts:
${initialHitCounts} -> " +
- "${updatedHitCounts}, read_counts: ${initialReadCounts} ->
${updatedReadCounts}")
-
- assertTrue(updatedHitCounts > initialHitCounts,
TOTAL_HIT_COUNTS_DID_NOT_INCREASE_MSG)
- assertTrue(updatedReadCounts > initialReadCounts,
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
- return true
+ assertTrue(updatedHitCounts > initialHitCounts,
TOTAL_HIT_COUNTS_DID_NOT_INCREASE_MSG)
+ assertTrue(updatedReadCounts > initialReadCounts,
TOTAL_READ_COUNTS_DID_NOT_INCREASE_MSG)
+ return true
+ }
}
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]