Skip to content

Commit 93394ab

Browse files
authored
IGNITE-27033: Сheckpoint command added (#12547)
1 parent 347ab41 commit 93394ab

File tree

8 files changed

+550
-1
lines changed

8 files changed

+550
-1
lines changed

modules/control-utility/src/test/java/org/apache/ignite/testsuites/IgniteControlUtilityTestSuite.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.ignite.util.GridCommandHandlerBrokenIndexTest;
2525
import org.apache.ignite.util.GridCommandHandlerCheckIncrementalSnapshotTest;
2626
import org.apache.ignite.util.GridCommandHandlerCheckIndexesInlineSizeTest;
27+
import org.apache.ignite.util.GridCommandHandlerCheckpointTest;
2728
import org.apache.ignite.util.GridCommandHandlerClusterByClassTest;
2829
import org.apache.ignite.util.GridCommandHandlerClusterByClassWithSSLTest;
2930
import org.apache.ignite.util.GridCommandHandlerConsistencyRepairCorrectnessTransactionalTest;
@@ -80,7 +81,8 @@
8081
BaselineEventsRemoteTest.class,
8182

8283
GridCommandHandlerConsistencyRepairCorrectnessTransactionalTest.class,
83-
GridCommandHandlerWalTest.class
84+
GridCommandHandlerWalTest.class,
85+
GridCommandHandlerCheckpointTest.class
8486
})
8587
public class IgniteControlUtilityTestSuite {
8688
}
Lines changed: 278 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,278 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.util;
19+
20+
import java.util.concurrent.CountDownLatch;
21+
import java.util.regex.Pattern;
22+
import org.apache.ignite.IgniteCache;
23+
import org.apache.ignite.cluster.ClusterState;
24+
import org.apache.ignite.configuration.DataRegionConfiguration;
25+
import org.apache.ignite.configuration.DataStorageConfiguration;
26+
import org.apache.ignite.configuration.IgniteConfiguration;
27+
import org.apache.ignite.internal.IgniteEx;
28+
import org.apache.ignite.internal.processors.cache.persistence.GridCacheDatabaseSharedManager;
29+
import org.apache.ignite.internal.processors.cache.persistence.checkpoint.CheckpointListener;
30+
import org.apache.ignite.testframework.GridTestUtils;
31+
import org.apache.ignite.testframework.ListeningTestLogger;
32+
import org.apache.ignite.testframework.LogListener;
33+
import org.junit.Test;
34+
35+
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
36+
37+
/** Test for checkpoint in control.sh command. */
38+
public class GridCommandHandlerCheckpointTest extends GridCommandHandlerAbstractTest {
39+
/** */
40+
private static final String PERSISTENT_REGION_NAME = "pds-reg";
41+
42+
/** */
43+
private final ListeningTestLogger listeningLog = new ListeningTestLogger(log);
44+
45+
/** */
46+
private final LogListener checkpointFinishedLsnr = LogListener.matches("Checkpoint finished").build();
47+
48+
/** */
49+
private boolean mixedConfig;
50+
51+
/** Latch for blocking checkpoint in timeout test. */
52+
private CountDownLatch blockCheckpointLatch;
53+
54+
/** */
55+
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
56+
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
57+
58+
listeningLog.registerListener(checkpointFinishedLsnr);
59+
60+
cfg.setGridLogger(listeningLog);
61+
62+
if (mixedConfig) {
63+
DataStorageConfiguration storageCfg = new DataStorageConfiguration();
64+
65+
storageCfg.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setName("default_in_memory_region")
66+
.setPersistenceEnabled(false));
67+
68+
if (igniteInstanceName.contains("persistent_instance")) {
69+
DataRegionConfiguration persistentRegionCfg = new DataRegionConfiguration();
70+
71+
storageCfg.setDataRegionConfigurations(persistentRegionCfg.setName(PERSISTENT_REGION_NAME)
72+
.setPersistenceEnabled(true));
73+
}
74+
75+
cfg.setDataStorageConfiguration(storageCfg);
76+
}
77+
else if (!persistenceEnable()) {
78+
cfg.setDataStorageConfiguration(null);
79+
}
80+
81+
return cfg;
82+
}
83+
84+
/** {@inheritDoc} */
85+
@Override protected void beforeTest() throws Exception {
86+
super.beforeTest();
87+
88+
stopAllGrids();
89+
cleanPersistenceDir();
90+
injectTestSystemOut();
91+
92+
checkpointFinishedLsnr.reset();
93+
blockCheckpointLatch = null;
94+
}
95+
96+
/** {@inheritDoc} */
97+
@Override protected void afterTest() throws Exception {
98+
if (blockCheckpointLatch != null) {
99+
blockCheckpointLatch.countDown();
100+
}
101+
102+
stopAllGrids();
103+
cleanPersistenceDir();
104+
105+
super.afterTest();
106+
}
107+
108+
/** Test checkpoint command with persistence enabled. */
109+
@Test
110+
public void testCheckpointPersistenceCluster() throws Exception {
111+
persistenceEnable(true);
112+
113+
IgniteEx srv = startGrids(2);
114+
IgniteEx cli = startClientGrid("client");
115+
116+
srv.cluster().state(ClusterState.ACTIVE);
117+
118+
IgniteCache<Integer, Integer> cacheCli = cli.getOrCreateCache(DEFAULT_CACHE_NAME);
119+
120+
cacheCli.put(1, 1);
121+
122+
assertEquals(EXIT_CODE_OK, execute("--checkpoint"));
123+
assertTrue(GridTestUtils.waitForCondition(checkpointFinishedLsnr::check, 10_000));
124+
assertFalse(testOut.toString().contains("persistence disabled"));
125+
126+
outputContains(": Checkpoint started");
127+
128+
testOut.reset();
129+
130+
checkpointFinishedLsnr.reset();
131+
132+
cacheCli.put(2, 2);
133+
134+
assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--reason", "test_reason"));
135+
136+
LogListener checkpointReasonLsnr = LogListener.matches("reason='test_reason'").build();
137+
138+
listeningLog.registerListener(checkpointReasonLsnr);
139+
140+
assertTrue(GridTestUtils.waitForCondition(checkpointFinishedLsnr::check, 10_000));
141+
assertTrue(GridTestUtils.waitForCondition(checkpointReasonLsnr::check, 10_000));
142+
assertFalse(testOut.toString().contains("persistence disabled"));
143+
144+
outputContains(": Checkpoint started");
145+
146+
testOut.reset();
147+
148+
checkpointFinishedLsnr.reset();
149+
150+
cacheCli.put(3, 3);
151+
152+
assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--wait-for-finish"));
153+
assertTrue(checkpointFinishedLsnr.check());
154+
assertFalse(testOut.toString().contains("persistence disabled"));
155+
}
156+
157+
/** Test checkpoint command with in-memory cluster. */
158+
@Test
159+
public void testCheckpointInMemoryCluster() throws Exception {
160+
persistenceEnable(false);
161+
162+
IgniteEx srv = startGrids(2);
163+
164+
startClientGrid("client");
165+
166+
srv.cluster().state(ClusterState.ACTIVE);
167+
168+
srv.createCache("testCache");
169+
170+
assertEquals(EXIT_CODE_OK, execute("--checkpoint"));
171+
assertFalse(checkpointFinishedLsnr.check());
172+
173+
outputContains("persistence disabled");
174+
}
175+
176+
/** Test checkpoint with timeout when checkpoint completes within timeout. */
177+
@Test
178+
public void testCheckpointTimeout() throws Exception {
179+
persistenceEnable(true);
180+
181+
IgniteEx srv = startGrids(1);
182+
183+
srv.cluster().state(ClusterState.ACTIVE);
184+
185+
assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--wait-for-finish", "--timeout", "1000"));
186+
187+
assertTrue(checkpointFinishedLsnr.check());
188+
189+
assertFalse(testOut.toString().contains("persistence disabled"));
190+
}
191+
192+
/** Test checkpoint timeout when checkpoint doesn't complete within timeout. */
193+
@Test
194+
public void testCheckpointTimeoutExceeded() throws Exception {
195+
persistenceEnable(true);
196+
197+
IgniteEx srv = startGrids(1);
198+
199+
srv.cluster().state(ClusterState.ACTIVE);
200+
201+
blockCheckpointLatch = new CountDownLatch(1);
202+
203+
GridCacheDatabaseSharedManager dbMgr = (GridCacheDatabaseSharedManager)srv.context().cache().context().database();
204+
205+
dbMgr.addCheckpointListener(new CheckpointListener() {
206+
@Override public void onMarkCheckpointBegin(Context ctx) {
207+
try {
208+
blockCheckpointLatch.await();
209+
}
210+
catch (InterruptedException e) {
211+
throw new RuntimeException(e);
212+
}
213+
}
214+
215+
@Override public void onCheckpointBegin(Context ctx) {
216+
// No-op
217+
}
218+
219+
@Override public void beforeCheckpointBegin(Context ctx) {
220+
// No-op
221+
}
222+
});
223+
224+
assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--wait-for-finish", "--timeout", "500"));
225+
226+
outputContains("Checkpoint started but not finished within timeout 500 ms");
227+
228+
blockCheckpointLatch.countDown();
229+
230+
assertTrue(GridTestUtils.waitForCondition(checkpointFinishedLsnr::check, 10_000));
231+
}
232+
233+
/** Mixed cluster test. */
234+
@Test
235+
public void testMixedCluster() throws Exception {
236+
mixedConfig = true;
237+
238+
IgniteEx node0 = startGrid("in-memory_instance");
239+
240+
node0.cluster().baselineAutoAdjustEnabled(false);
241+
242+
IgniteEx node1 = startGrid("persistent_instance");
243+
244+
node0.cluster().state(ClusterState.ACTIVE);
245+
246+
assertEquals(2, node0.cluster().nodes().size());
247+
248+
DataStorageConfiguration node0Storage = node0.configuration().getDataStorageConfiguration();
249+
DataStorageConfiguration node1Storage = node1.configuration().getDataStorageConfiguration();
250+
251+
DataRegionConfiguration node0Dflt = node0Storage.getDefaultDataRegionConfiguration();
252+
DataRegionConfiguration node1Dflt = node1Storage.getDefaultDataRegionConfiguration();
253+
254+
assertEquals(node0Dflt.getName(), node1Dflt.getName());
255+
assertEquals(node0Dflt.isPersistenceEnabled(), node1Dflt.isPersistenceEnabled());
256+
assertEquals(node0Dflt.getMaxSize(), node1Dflt.getMaxSize());
257+
258+
DataRegionConfiguration[] node1Regions = node1Storage.getDataRegionConfigurations();
259+
assertEquals(1, node1Regions.length);
260+
261+
DataRegionConfiguration persistentRegion = node1Regions[0];
262+
263+
assertEquals(PERSISTENT_REGION_NAME, persistentRegion.getName());
264+
assertEquals(true, persistentRegion.isPersistenceEnabled());
265+
266+
assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--wait-for-finish"));
267+
268+
assertTrue(checkpointFinishedLsnr.check());
269+
270+
outputContains("persistence disabled");
271+
outputContains("Checkpoint finished");
272+
}
273+
274+
/** */
275+
private void outputContains(String regexp) {
276+
assertTrue(Pattern.compile(regexp).matcher(testOut.toString()).find());
277+
}
278+
}

modules/core/src/main/java/org/apache/ignite/internal/management/IgniteCommandRegistry.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import org.apache.ignite.internal.management.baseline.BaselineCommand;
2525
import org.apache.ignite.internal.management.cache.CacheCommand;
2626
import org.apache.ignite.internal.management.cdc.CdcCommand;
27+
import org.apache.ignite.internal.management.checkpoint.CheckpointCommand;
2728
import org.apache.ignite.internal.management.consistency.ConsistencyCommand;
2829
import org.apache.ignite.internal.management.defragmentation.DefragmentationCommand;
2930
import org.apache.ignite.internal.management.diagnostic.DiagnosticCommand;
@@ -58,6 +59,7 @@ public IgniteCommandRegistry() {
5859
new TxCommand(),
5960
new CacheCommand(),
6061
new WalCommand(),
62+
new CheckpointCommand(),
6163
new DiagnosticCommand(),
6264
new EncryptionCommand(),
6365
new KillCommand(),
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
/*
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
18+
package org.apache.ignite.internal.management.checkpoint;
19+
20+
import java.util.Collection;
21+
import java.util.function.Consumer;
22+
import org.apache.ignite.cluster.ClusterNode;
23+
import org.apache.ignite.internal.management.api.CommandUtils;
24+
import org.apache.ignite.internal.management.api.ComputeCommand;
25+
import org.jetbrains.annotations.Nullable;
26+
27+
/** Checkpoint command. */
28+
public class CheckpointCommand implements ComputeCommand<CheckpointCommandArg, String> {
29+
/** {@inheritDoc} */
30+
@Override public Class<CheckpointTask> taskClass() {
31+
return CheckpointTask.class;
32+
}
33+
34+
/** {@inheritDoc} */
35+
@Override public String description() {
36+
return "Trigger checkpoint";
37+
}
38+
39+
/** {@inheritDoc} */
40+
@Override public Class<CheckpointCommandArg> argClass() {
41+
return CheckpointCommandArg.class;
42+
}
43+
44+
/** {@inheritDoc} */
45+
@Override public @Nullable Collection<ClusterNode> nodes(Collection<ClusterNode> nodes, CheckpointCommandArg arg) {
46+
return CommandUtils.servers(nodes);
47+
}
48+
49+
/** {@inheritDoc} */
50+
@Override public void printResult(CheckpointCommandArg arg, String res, Consumer<String> printer) {
51+
printer.accept(res);
52+
}
53+
}

0 commit comments

Comments
 (0)