Index: modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CheckpointFakeBlockingRepoducer.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CheckpointFakeBlockingRepoducer.java b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CheckpointFakeBlockingRepoducer.java new file mode 100644 --- /dev/null (date 1625343626415) +++ b/modules/core/src/test/java/org/apache/ignite/internal/processors/cache/persistence/CheckpointFakeBlockingRepoducer.java (date 1625343626415) @@ -0,0 +1,89 @@ +/* + * 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. + */ + +package org.apache.ignite.internal.processors.cache.persistence; + +import org.apache.ignite.cache.CacheAtomicityMode; +import org.apache.ignite.cache.CacheMode; +import org.apache.ignite.cluster.ClusterState; +import org.apache.ignite.configuration.CacheConfiguration; +import org.apache.ignite.configuration.DataRegionConfiguration; +import org.apache.ignite.configuration.DataStorageConfiguration; +import org.apache.ignite.configuration.IgniteConfiguration; +import org.apache.ignite.internal.IgniteEx; +import org.apache.ignite.testframework.ListeningTestLogger; +import org.apache.ignite.testframework.LogListener; +import org.apache.ignite.testframework.junits.common.GridCommonAbstractTest; +import org.junit.Test; + +/** + */ +public class CheckpointFakeBlockingRepoducer extends GridCommonAbstractTest { + /** Failure handler timeout. */ + public static final int FAILURE_HANDLER_TIMEOUT = 10000; + + /** Checkpoint frequency. */ + public static final int CHECKPOINT_FREQUENCY = FAILURE_HANDLER_TIMEOUT * 2; + + /** Test logger. */ + private final ListeningTestLogger testLog = new ListeningTestLogger(log); + /** + * {@inheritDoc} + */ + @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { + return super.getConfiguration(igniteInstanceName) + .setFailureDetectionTimeout(FAILURE_HANDLER_TIMEOUT) + .setDataStorageConfiguration(new DataStorageConfiguration() + .setDefaultDataRegionConfiguration(new DataRegionConfiguration() + .setPersistenceEnabled(true)) + .setCheckpointFrequency(CHECKPOINT_FREQUENCY)) + .setCacheConfiguration(new CacheConfiguration<>(DEFAULT_CACHE_NAME) + .setCacheMode(CacheMode.REPLICATED) + .setAtomicityMode(CacheAtomicityMode.TRANSACTIONAL)) + .setGridLogger(testLog); + } + + /** {@inheritDoc} */ + @Override protected void afterTest() throws Exception { + stopAllGrids(); + + cleanPersistenceDir(); + } + + /** {@inheritDoc} */ + @Override protected void beforeTest() throws Exception { + cleanPersistenceDir(); + } + + /** */ + @Test + public void test() throws Exception { + LogListener blockListener = LogListener.matches("Blocked system-critical thread has been detected. " + + "This can lead to cluster-wide undefined behaviour [workerName=db-checkpoint-thread") + .build(); + + testLog.registerListener(blockListener); + + IgniteEx ig = startGrid(0); + ig.cluster().state(ClusterState.ACTIVE); + + awaitPartitionMapExchange(); + + assertFalse("Blocked system-critical thread has been detected: 'db-checkpoint-thread'", + blockListener.check(CHECKPOINT_FREQUENCY * 3)); + } +} Index: modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java (revision 468c41f8410289ec14a6326ae7af05c1d5aa7055) +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/Checkpointer.java (date 1625343398258) @@ -815,6 +815,8 @@ try { wait(remaining); + log.warning(">>>>>> Heartbeat after wait: " + heartbeatTs()); + remaining = U.nanosToMillis(scheduledCp.nextCpNanos() - System.nanoTime()); } finally { Index: modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointContextImpl.java IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 =================================================================== diff --git a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointContextImpl.java b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointContextImpl.java --- a/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointContextImpl.java (revision 468c41f8410289ec14a6326ae7af05c1d5aa7055) +++ b/modules/core/src/main/java/org/apache/ignite/internal/processors/cache/persistence/checkpoint/CheckpointContextImpl.java (date 1625343398249) @@ -101,7 +101,16 @@ try { GridFutureAdapter res = new GridFutureAdapter<>(); - res.listen(fut -> heartbeatUpdater.updateHeartbeat()); + res.listen(fut -> { + try { + Thread.sleep(10); + } + catch (InterruptedException e) { + // Ignore. + } + + heartbeatUpdater.updateHeartbeat(); + }); asyncRunner.execute(U.wrapIgniteFuture(cmd, res));