IGNITE-27033: Сheckpoint command added#12547
Conversation
| import org.apache.ignite.internal.management.api.ComputeCommand; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| public class CheckpointForceCommand implements ComputeCommand<CheckpointForceCommandArg, String> { |
There was a problem hiding this comment.
This logic must be in CheckpointCommand itself.
So the desired syntax is:
> ./control.sh --checkpoint
> ./control.sh --checkpoint --reason "After data load checkpoint"
> ./control.sh --checkoint --wait-for-finish --timeout 60000
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override protected String run(@Nullable CheckpointForceCommandArg arg) throws IgniteException { |
There was a problem hiding this comment.
We must check if persistence enabled on node with the:
if (!CU.isPersistenceEnabled(ignite.configuration())) {
throw new IgniteException("Can't checkpoint on in-memory node"); // Or return some result here.
}
|
@DEADripER please, fix code style violations. |
| import org.apache.ignite.internal.management.api.ComputeCommand; | ||
| import org.jetbrains.annotations.Nullable; | ||
|
|
||
| /** Checkpoint command class*/ |
There was a problem hiding this comment.
typo: /** Checkpoint command class*/ -> /** Checkpoint command. */
| CheckpointProgress checkpointfut = dbMgr.forceCheckpoint(reason); | ||
|
|
||
| if (waitForFinish) { | ||
| if (timeout != null && timeout > 0) { |
There was a problem hiding this comment.
if (timeout != null && timeout > 0)
checkpointfut.futureFor(CheckpointState.FINISHED).get(timeout, TimeUnit.MILLISECONDS);
else
checkpointfut.futureFor(CheckpointState.FINISHED).get();
| } | ||
| return "Checkpoint completed on node: " + ignite.localNode().id(); | ||
| } | ||
| else { |
There was a problem hiding this comment.
else
return "Checkpoint triggered on node: " + ignite.localNode().id();
|
|
||
| /** {@inheritDoc} */ | ||
| @Override protected String run(@Nullable CheckpointCommandArg arg) throws IgniteException { | ||
| if (!CU.isPersistenceEnabled(ignite.configuration())) { |
There was a problem hiding this comment.
One line statements written without quote.
Please, take a look at style guide:
https://cwiki.apache.org/confluence/display/IGNITE/Coding+Guidelines
if (!CU.isPersistenceEnabled(ignite.configuration()))
throw new IgniteException("Can't checkpoint on in-memory node");
| throw new IgniteException("Can't checkpoint on in-memory node"); | ||
| } | ||
|
|
||
| String reason = arg != null && arg.reason() != null ? arg.reason() : "control.sh"; |
There was a problem hiding this comment.
Let's skip arg null checks here and in other places.
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override protected String run(@Nullable CheckpointCommandArg arg) throws IgniteException { |
There was a problem hiding this comment.
Please, remove Nullable annotation.
| stopAllGrids(); | ||
| cleanPersistenceDir(); | ||
| injectTestSystemOut(); | ||
| super.beforeTest(); |
There was a problem hiding this comment.
super.beforeTest(); must be invoked first.
| @Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception { | ||
| IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName); | ||
|
|
||
| if (clusterState == 1) |
There was a problem hiding this comment.
Let's use
GridCommandHandlerAbstractTest#persistenceEnable instead of clusterState flag
|
|
||
| import java.util.Objects; | ||
| import java.util.regex.Pattern; | ||
|
|
| /** Test for checkpoint in control.sh command. */ | ||
| public class GridCommandHandlerCheckpointTest extends GridCommandHandlerAbstractTest { | ||
| /** */ | ||
| protected final ListeningTestLogger listeningLog = new ListeningTestLogger(log); |
| IgniteEx srv = startGrids(2); | ||
| IgniteEx cli = startClientGrid("client"); | ||
|
|
||
| LogListener checkpointFinishedLsnr = LogListener.matches("Checkpoint finished").build(); |
There was a problem hiding this comment.
To avoid duplication of creating checkpointFinishedLsnr in each test, let's create a field and reuse it across all tests:
/** */
private final ListeningTestLogger listeningLog = new ListeningTestLogger(log);
/** */
private final LogListener checkpointFinishedLsnr = LogListener.matches("Checkpoint finished").build();
/** */
@Override protected IgniteConfiguration getConfiguration(String igniteInstanceName) throws Exception {
IgniteConfiguration cfg = super.getConfiguration(igniteInstanceName);
if (!persistenceEnable())
cfg.setDataStorageConfiguration(null);
listeningLog.registerListener(checkpointFinishedLsnr);
cfg.setGridLogger(listeningLog);
return cfg;
}
| srv.createCache("testCache"); | ||
| assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--checkpoint")); | ||
|
|
||
| String out = testOut.toString(); |
There was a problem hiding this comment.
Let's move it after the line outputContains(...).
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override public @Nullable Collection<ClusterNode> nodes( |
There was a problem hiding this comment.
Let's place on a single line.
@Override public @Nullable Collection<ClusterNode> nodes(Collection<ClusterNode> nodes, CheckpointCommandArg arg) {
|
|
||
| /** */ | ||
| @Argument(description = "Timeout in milliseconds", optional = true) | ||
| private Long timeout; |
There was a problem hiding this comment.
Maybe we could use a primitive type?
private long timeout = -1;
| } | ||
|
|
||
| /** {@inheritDoc} */ | ||
| @Override protected String run(CheckpointCommandArg arg) throws IgniteException { |
There was a problem hiding this comment.
I suggest refactoring slightly to make the code easier to read:
/** {@inheritDoc} */
@Override protected String run(CheckpointCommandArg arg) throws IgniteException {
if (!CU.isPersistenceEnabled(ignite.configuration()))
throw new IgniteException("Can't checkpoint on in-memory node");
try {
GridCacheDatabaseSharedManager dbMgr = (GridCacheDatabaseSharedManager)ignite.context().cache().context().database();
CheckpointProgress checkpointfut = dbMgr.forceCheckpoint(arg.reason());
if (!arg.waitForFinish())
return "Checkpoint triggered on node: " + ignite.localNode().id();
long timeout = arg.timeout();
if (timeout > 0)
checkpointfut.futureFor(CheckpointState.FINISHED).get(timeout, TimeUnit.MILLISECONDS);
else
checkpointfut.futureFor(CheckpointState.FINISHED).get();
return "Checkpoint completed on node: " + ignite.localNode().id();
}
catch (Exception e) {
throw new IgniteException("Failed to force checkpoint on node: " + ignite.localNode().id(), e);
}
}
There was a problem hiding this comment.
+, thank you for refactoring
| @Override protected void writeExternalData(ObjectOutput out) throws IOException { | ||
| U.writeString(out, reason); | ||
| out.writeBoolean(waitForFinish); | ||
| out.writeObject(timeout); |
| cacheCli.put(1, 1); | ||
|
|
||
| assertEquals(EXIT_CODE_OK, execute("--checkpoint")); | ||
|
|
| assertEquals(EXIT_CODE_OK, execute("--checkpoint")); | ||
|
|
||
| assertTrue(GridTestUtils.waitForCondition(checkpointFinishedLsnr::check, 10_000)); | ||
|
|
|
|
||
| assertTrue(GridTestUtils.waitForCondition(checkpointFinishedLsnr::check, 10_000)); | ||
|
|
||
| assertFalse(testOut.toString().contains("PDS disabled")); |
| assertFalse(testOut.toString().contains("PDS disabled")); | ||
| outputContains(": Checkpoint started"); | ||
|
|
||
| testOut.reset(); |
| startClientGrid("client"); | ||
| srv.cluster().state(ClusterState.ACTIVE); | ||
|
|
||
| srv.createCache("testCache"); |
|
|
||
| srv.createCache("testCache"); | ||
| assertEquals(EXIT_CODE_OK, execute("--checkpoint")); | ||
|
|
| public void testCheckpointTimeout() throws Exception { | ||
| persistenceEnable(true); | ||
|
|
||
| IgniteEx srv = startGrids(1); |
| public void testMixedCluster() throws Exception { | ||
| mixedConfig = true; | ||
|
|
||
| IgniteEx node0 = startGrid("in-memory_instance"); |
| DataRegionConfiguration[] node1Regions = node1Storage.getDataRegionConfigurations(); | ||
| assertEquals(1, node1Regions.length); | ||
|
|
||
| DataRegionConfiguration persistentRegion = node1Regions[0]; |
|
|
||
| assertEquals(EXIT_CODE_OK, execute("--checkpoint", "--wait-for-finish")); | ||
|
|
||
| assertTrue(checkpointFinishedLsnr.check()); |
|
|
||
| if (mixedConfig) { | ||
| DataStorageConfiguration storageCfg = new DataStorageConfiguration(); | ||
| DataRegionConfiguration dfltRegionCfg = new DataRegionConfiguration(); |
There was a problem hiding this comment.
Single usage.
Let's inline dfltDataRegion:
storageCfg.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setName("default_in_memory_region").setPersistenceEnabled(false));
| private final LogListener checkpointFinishedLsnr = LogListener.matches("Checkpoint finished").build(); | ||
|
|
||
| /** */ | ||
| private boolean mixedConfig = false; |
There was a problem hiding this comment.
useless initialization. Default value false, already.
| private boolean mixedConfig = false; | ||
|
|
||
| /** */ | ||
| private static final String persistentRegionName = "pds-reg"; |
There was a problem hiding this comment.
constants must be in UPPER_CASE.
Please, move constant to the top of class.
| IgniteCache<Integer, Integer> cacheCli = cli.getOrCreateCache(DEFAULT_CACHE_NAME); | ||
|
|
||
| cacheSrv.put(1, 1); | ||
| cacheCli.put(1, 1); |
There was a problem hiding this comment.
It's enough to put from single cache instance, only.
Please, remove cacheSrv.put here and below.
|
| DataStorageConfiguration storageCfg = new DataStorageConfiguration(); | ||
|
|
||
| storageCfg.setDefaultDataRegionConfiguration(new DataRegionConfiguration().setName("default_in_memory_region") | ||
| .setPersistenceEnabled(false)); |
There was a problem hiding this comment.
Please use correct indent (4 spaces) next time
| else if (!persistenceEnable()) { | ||
| cfg.setDataStorageConfiguration(null); | ||
| } |
There was a problem hiding this comment.
Also, we don't use braces for one-line "if" statements, see Ignite codestyle



Thank you for submitting the pull request to the Apache Ignite.
In order to streamline the review of the contribution
we ask you to ensure the following steps have been taken:
The Contribution Checklist
The description explains WHAT and WHY was made instead of HOW.
The following pattern must be used:
IGNITE-XXXX Change summarywhereXXXX- number of JIRA issue.(see the Maintainers list)
the
green visaattached to the JIRA ticket (see TC.Bot: Check PR)Notes
If you need any help, please email dev@ignite.apache.org or ask anу advice on http://asf.slack.com #ignite channel.