This is an automated email from the ASF dual-hosted git repository.
sergey-chugunov-1985 pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/ignite.git
The following commit(s) were added to refs/heads/master by this push:
new 4cac38bd7e8 IGNITE-28996 Idle Verify utility shouldn't use Java's
ForkJoinPool (#13494)
4cac38bd7e8 is described below
commit 4cac38bd7e817b6ba2d15c584892a3bb85e00f18
Author: Vladimir Steshin <[email protected]>
AuthorDate: Fri Aug 21 11:32:15 2026 +0300
IGNITE-28996 Idle Verify utility shouldn't use Java's ForkJoinPool (#13494)
---
docs/_docs/tools/control-script.adoc | 16 ++++++++
.../apache/ignite/util/GridCommandHandlerTest.java | 10 +++--
.../cache/VerifyBackupPartitionsTask.java | 28 ++++++++------
.../consistency/ConsistencyRepairTask.java | 10 +++--
.../processors/cache/verify/IdleVerifyUtility.java | 4 +-
.../internal/processors/pool/PoolProcessor.java | 43 ++++++++++++++++++++++
6 files changed, 90 insertions(+), 21 deletions(-)
diff --git a/docs/_docs/tools/control-script.adoc
b/docs/_docs/tools/control-script.adoc
index fd96397f261..edc87dfa66d 100644
--- a/docs/_docs/tools/control-script.adoc
+++ b/docs/_docs/tools/control-script.adoc
@@ -755,6 +755,17 @@ To cancel a running `idle_verify` operation, use the
`--cancel` argument:
control.sh --cache idle_verify --cancel
----
+[NOTE]
+====
+[discrete]
+`idle_verify` command uses its own utility thread pool of default size `Total
CPUs - 2` with the minimum of `4` threads.
+The pool size might be adjusted at node startup with the system property
+
+`-DIGNITE_IDLE_VERIFY_POOL_SIZE=...`.
+[discrete]
+These pool threads expire after some time being unused.
+====
+
=== Repairing cache consistency
[WARNING]
====
@@ -823,6 +834,11 @@ control.bat --enable-experimental --consistency status
----
--
+[NOTE]
+====
+Consistency `repair` uses the same thread pool as `idle_verify`.
+====
+
=== Partition update counters finalization
The command allows fo finalize partition update counters after the manual
repair.
diff --git
a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
index 872fb04cce0..38bac2352b1 100644
---
a/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
+++
b/modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerTest.java
@@ -251,6 +251,8 @@ public class GridCommandHandlerTest extends
GridCommandHandlerClusterPerMethodAb
super.afterTest();
listeningLog = null;
+
+ VerifyBackupPartitionsTask.EXECUTOR_SERVICE = null;
}
/** {@inheritDoc} */
@@ -435,7 +437,7 @@ public class GridCommandHandlerTest extends
GridCommandHandlerClusterPerMethodAb
}, false);
}
- /** */
+ /** TODO: revise in https://issues.apache.org/jira/browse/IGNITE-29002 */
@Test
public void testIdleVerifyCancelBeforeCalcPartitionHashStarted() throws
Exception {
doTestCancelIdleVerify((beforeCancelLatch, afterCancelLatch) -> {
@@ -456,11 +458,11 @@ public class GridCommandHandlerTest extends
GridCommandHandlerClusterPerMethodAb
}
};
- VerifyBackupPartitionsTask.poolSupplier = () -> pool;
+ VerifyBackupPartitionsTask.EXECUTOR_SERVICE = pool;
}, false);
}
- /** */
+ /** TODO: revise in https://issues.apache.org/jira/browse/IGNITE-29002 */
@Test
public void testIdleVerifyCancelWhileCalcPartitionHashRunning() throws
Exception {
for (boolean checkCrc : new boolean[] {false, true}) {
@@ -508,7 +510,7 @@ public class GridCommandHandlerTest extends
GridCommandHandlerClusterPerMethodAb
}
};
- VerifyBackupPartitionsTask.poolSupplier = () -> pool;
+ VerifyBackupPartitionsTask.EXECUTOR_SERVICE = pool;
}, checkCrc);
assertTrue("All tasks must be cancelled",
interruptedOnCancel.get());
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/VerifyBackupPartitionsTask.java
b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/VerifyBackupPartitionsTask.java
index 54c5f1c41a0..895b5693a41 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/management/cache/VerifyBackupPartitionsTask.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/management/cache/VerifyBackupPartitionsTask.java
@@ -31,7 +31,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.BooleanSupplier;
-import java.util.function.Supplier;
import java.util.regex.Pattern;
import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
@@ -57,7 +56,6 @@ import
org.apache.ignite.internal.processors.cache.persistence.file.FilePageStor
import org.apache.ignite.internal.processors.cache.verify.GridNotIdleException;
import org.apache.ignite.internal.processors.cache.verify.PartitionHashRecord;
import org.apache.ignite.internal.processors.task.GridInternal;
-import org.apache.ignite.internal.thread.pool.IgniteForkJoinPool;
import org.apache.ignite.internal.util.typedef.F;
import org.apache.ignite.internal.util.typedef.internal.U;
import org.apache.ignite.lang.IgniteInClosure;
@@ -65,6 +63,7 @@ import org.apache.ignite.resources.IgniteInstanceResource;
import org.apache.ignite.resources.LoggerResource;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
+import org.jetbrains.annotations.TestOnly;
import static java.util.Collections.emptyMap;
import static org.apache.ignite.internal.pagemem.PageIdAllocator.FLAG_DATA;
@@ -84,6 +83,9 @@ import static
org.apache.ignite.internal.processors.cache.verify.IdleVerifyUtili
*/
@GridInternal
public class VerifyBackupPartitionsTask extends
ComputeTaskAdapter<CacheIdleVerifyCommandArg, IdleVerifyResult> {
+ /** */
+ private static final long serialVersionUID = 0L;
+
/** Error thrown when idle_verify is called on an inactive cluster with
persistence. */
public static final String IDLE_VERIFY_ON_INACTIVE_CLUSTER_ERROR_MESSAGE =
"Cannot perform the operation because " +
"the cluster is inactive.";
@@ -94,16 +96,17 @@ public class VerifyBackupPartitionsTask extends
ComputeTaskAdapter<CacheIdleVeri
/** Checkpoint reason. */
public static final String CP_REASON = "VerifyBackupPartitions";
- /** Shared for tests. */
- public static Supplier<ExecutorService> poolSupplier =
IgniteForkJoinPool::commonPool;
+ /**
+ * Only for tests. Overrides the default pool.
+ * TODO: remove in https://issues.apache.org/jira/browse/IGNITE-29002
+ */
+ @TestOnly
+ public static volatile ExecutorService EXECUTOR_SERVICE;
/** Injected logger. */
@LoggerResource
private IgniteLogger log;
- /** */
- private static final long serialVersionUID = 0L;
-
/** {@inheritDoc} */
@NotNull @Override public Map<? extends ComputeJob, ClusterNode> map(
List<ClusterNode> subgrid,
@@ -335,9 +338,7 @@ public class VerifyBackupPartitionsTask extends
ComputeTaskAdapter<CacheIdleVeri
}
/** */
- private List<Future<Map<PartitionKey, PartitionHashRecord>>>
calcPartitionHashAsync(
- Set<Integer> grpIds
- ) {
+ private List<Future<Map<PartitionKey, PartitionHashRecord>>>
calcPartitionHashAsync(Set<Integer> grpIds) {
List<Future<Map<PartitionKey, PartitionHashRecord>>>
partHashCalcFutures = new ArrayList<>();
for (Integer grpId : grpIds) {
@@ -346,10 +347,13 @@ public class VerifyBackupPartitionsTask extends
ComputeTaskAdapter<CacheIdleVeri
if (grpCtx == null)
continue;
- ExecutorService pool = poolSupplier.get();
+ ExecutorService execSrvs = EXECUTOR_SERVICE;
+
+ if (execSrvs == null)
+ execSrvs =
ignite.context().pools().getIdleVerifyExecutorService();
for (GridDhtLocalPartition part :
grpCtx.topology().currentLocalPartitions())
- partHashCalcFutures.add(calculatePartitionHashAsync(pool,
grpCtx, part, this::isCancelled));
+
partHashCalcFutures.add(calculatePartitionHashAsync(execSrvs, grpCtx, part,
this::isCancelled));
}
return partHashCalcFutures;
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/management/consistency/ConsistencyRepairTask.java
b/modules/core/src/main/java/org/apache/ignite/internal/management/consistency/ConsistencyRepairTask.java
index 0843658042c..1702d1097bd 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/management/consistency/ConsistencyRepairTask.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/management/consistency/ConsistencyRepairTask.java
@@ -24,6 +24,7 @@ import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.ExecutionException;
+import java.util.concurrent.ExecutorService;
import java.util.concurrent.atomic.AtomicReference;
import java.util.stream.Collectors;
import javax.cache.CacheException;
@@ -40,7 +41,6 @@ import
org.apache.ignite.internal.processors.cache.distributed.dht.topology.Grid
import
org.apache.ignite.internal.processors.cache.distributed.near.consistency.IgniteIrreparableConsistencyViolationException;
import org.apache.ignite.internal.processors.cache.persistence.CacheDataRow;
import org.apache.ignite.internal.thread.context.Scope;
-import org.apache.ignite.internal.thread.pool.IgniteForkJoinPool;
import org.apache.ignite.internal.util.GridConcurrentHashSet;
import org.apache.ignite.internal.util.lang.GridCursor;
import org.apache.ignite.internal.util.typedef.F;
@@ -102,8 +102,12 @@ public class ConsistencyRepairTask extends
AbstractConsistencyTask<ConsistencyRe
@Override protected String run(ConsistencyRepairCommandArg arg) throws
IgniteException {
AtomicReference<Exception> err = new AtomicReference<>();
+ ExecutorService execSrvc =
ignite.context().pools().getIdleVerifyExecutorService();
+
+ // Consisnency Repair and Idle Verify are usually companion tasks.
Thay share the same thread pool currently
+ // allocated by Idle Verify.
Map<Boolean, List<IgniteBiTuple<Integer, String>>> res =
Arrays.stream(arg.partitions())
- .mapToObj(p -> F.t(p,
IgniteForkJoinPool.commonPool().submit(() -> processPartition(p, arg))))
+ .mapToObj(p -> F.t(p, execSrvc.submit(() ->
processPartition(p, arg))))
.map(t -> {
try {
return F.t(t.get1(), t.get2().get());
@@ -126,7 +130,7 @@ public class ConsistencyRepairTask extends
AbstractConsistencyTask<ConsistencyRe
makeResult(res, false, resStr, CONSISTENCY_VIOLATIONS_FOUND);
- return resStr.length() == 0 ? null : resStr.toString();
+ return resStr.isEmpty() ? null : resStr.toString();
}
/**
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
index 1dc7c5df03e..9e9b2b6a90c 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/verify/IdleVerifyUtility.java
@@ -123,7 +123,7 @@ public class IdleVerifyUtility {
for (int pageNo = 0; pageNo < pageStore.pages(); pageId++,
pageNo++) {
if (cancelled != null && cancelled.getAsBoolean())
- throw new IgniteException();
+ throw new IgniteException("Checking of partitions page CRC
sum has been cancelled.");
buf.clear();
@@ -311,7 +311,7 @@ public class IdleVerifyUtility {
while (it.hasNextX()) {
if (cancelled != null && cancelled.getAsBoolean())
- throw new IgniteCheckedException("Caclulate partition hash
cancelled.");
+ throw new IgniteCheckedException("Partition hash calculation
has been cancelled.");
CacheDataRow row = it.nextX();
diff --git
a/modules/core/src/main/java/org/apache/ignite/internal/processors/pool/PoolProcessor.java
b/modules/core/src/main/java/org/apache/ignite/internal/processors/pool/PoolProcessor.java
index 27d9642a96d..e6b41bc526c 100644
---
a/modules/core/src/main/java/org/apache/ignite/internal/processors/pool/PoolProcessor.java
+++
b/modules/core/src/main/java/org/apache/ignite/internal/processors/pool/PoolProcessor.java
@@ -31,6 +31,7 @@ import org.apache.ignite.IgniteCheckedException;
import org.apache.ignite.IgniteException;
import org.apache.ignite.IgniteLogger;
import org.apache.ignite.IgniteSystemProperties;
+import org.apache.ignite.SystemProperty;
import org.apache.ignite.configuration.ExecutorConfiguration;
import org.apache.ignite.configuration.IgniteConfiguration;
import org.apache.ignite.failure.FailureContext;
@@ -144,6 +145,14 @@ public class PoolProcessor extends GridProcessorAdapter {
*/
public static final long DFLT_PERIODIC_STARVATION_CHECK_FREQ = 30 * 1000L;
+ /** */
+ @SystemProperty(value = "Idle verify utility thread pool size.", type =
Integer.class,
+ defaults = "Total available CPUs minus 2, but at least 4 threads.")
+ public static final String IDLE_VERIFY_POOL_SIZE_PROPERTY =
"IGNITE_IDLE_VERIFY_POOL_SIZE";
+
+ /** */
+ private static final int DFLT_IDLE_VERIFY_POOL_SIZE = Math.max(4,
IgniteConfiguration.AVAILABLE_PROC_CNT - 2);
+
/** Executor service. */
@GridToStringExclude
private IgniteThreadPoolExecutor execSvc;
@@ -164,6 +173,10 @@ public class PoolProcessor extends GridProcessorAdapter {
@GridToStringExclude
private IgniteThreadPoolExecutor mgmtExecSvc;
+ /** Idle verify executor service. */
+ @GridToStringExclude
+ private IgniteThreadPoolExecutor idleVerifyExecSvc;
+
/** P2P executor service. */
@GridToStringExclude
private IgniteThreadPoolExecutor p2pExecSvc;
@@ -377,6 +390,22 @@ public class PoolProcessor extends GridProcessorAdapter {
mgmtExecSvc.allowCoreThreadTimeOut(true);
+ int idleVerifyPoolSz =
IgniteSystemProperties.getInteger(IDLE_VERIFY_POOL_SIZE_PROPERTY,
DFLT_IDLE_VERIFY_POOL_SIZE);
+
+ validateThreadPoolSize(idleVerifyPoolSz, "idle verify");
+
+ idleVerifyExecSvc = new IgniteThreadPoolExecutor(
+ "idleVerify",
+ cfg.getIgniteInstanceName(),
+ idleVerifyPoolSz,
+ idleVerifyPoolSz,
+ DFLT_THREAD_KEEP_ALIVE_TIME,
+ new LinkedBlockingQueue<>(),
+ GridIoPolicy.UNDEFINED,
+ oomeHnd);
+
+ idleVerifyExecSvc.allowCoreThreadTimeOut(true);
+
// Note that since we use 'LinkedBlockingQueue', number of
// maximum threads has no effect.
// Note, that we do not pre-start threads here as class loading pool
may
@@ -622,6 +651,7 @@ public class PoolProcessor extends GridProcessorAdapter {
monitorExecutor("GridSystemExecutor", sysExecSvc);
monitorExecutor("GridClassLoadingExecutor", p2pExecSvc);
monitorExecutor("GridManagementExecutor", mgmtExecSvc);
+ monitorExecutor("GridIdleVerifyExecutor", idleVerifyExecSvc);
monitorExecutor("GridAffinityExecutor", affExecSvc);
monitorExecutor("GridCallbackExecutor", callbackExecSvc);
monitorExecutor("GridQueryExecutor", qryExecSvc);
@@ -898,6 +928,15 @@ public class PoolProcessor extends GridProcessorAdapter {
return mgmtExecSvc;
}
+ /**
+ * Executor service that is in charge to run idle verify routines.
+ *
+ * @return Thread pool implementation to be used idle verify routines.
+ */
+ public IgniteThreadPoolExecutor getIdleVerifyExecutorService() {
+ return idleVerifyExecSvc;
+ }
+
/**
* @return Thread pool implementation to be used for peer class loading
* requests handling.
@@ -1110,6 +1149,10 @@ public class PoolProcessor extends GridProcessorAdapter {
mgmtExecSvc = null;
+ U.shutdownNow(getClass(), idleVerifyExecSvc, log);
+
+ idleVerifyExecSvc = null;
+
U.shutdownNow(getClass(), p2pExecSvc, log);
p2pExecSvc = null;