Skip to content

Commit baf2c91

Browse files
IGNITE-15328 Consistency recovery command (Read Repair via control.ch) should support cancellation (apache#9409)
1 parent 045d244 commit baf2c91

File tree

12 files changed

+447
-22
lines changed

12 files changed

+447
-22
lines changed

docs/_docs/sql-reference/operational-commands.adoc

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -334,7 +334,7 @@ KILL CONTINUOUS '6fa749ee-7cf8-4635-be10-36a1c75267a7_54321' '6fa749ee-7cf8-4635
334334

335335
== KILL SERVICE
336336

337-
The `KILL SERVICE` command allows you to cance a running service.
337+
The `KILL SERVICE` command allows you to cancel a running service.
338338

339339
[tabs]
340340
--
@@ -370,3 +370,25 @@ control.bat --kill SERVICE name
370370

371371
* `name` - corresponds to the name you selected for the service upon the deployment time.
372372
You can always find it with the link:monitoring-metrics/system-views#services[SERVICES] view.
373+
374+
375+
== KILL CONSISTENCY repair/check operations
376+
377+
The `KILL CONSISTENCY` command allows you to cancel all running consistency repair/check operations.
378+
379+
[tabs]
380+
--
381+
382+
tab:Unix[]
383+
[source,bash]
384+
----
385+
./control.sh --kill CONSISTENCY
386+
----
387+
388+
tab:Windows[]
389+
[source,bash]
390+
----
391+
control.bat --kill CONSISTENCY
392+
----
393+
394+
--

modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/consistency/ConsistencyCommand.java

Lines changed: 31 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -20,13 +20,15 @@
2020
import java.util.LinkedHashMap;
2121
import java.util.Map;
2222
import java.util.logging.Logger;
23+
import org.apache.ignite.IgniteCheckedException;
2324
import org.apache.ignite.internal.client.GridClient;
2425
import org.apache.ignite.internal.client.GridClientConfiguration;
2526
import org.apache.ignite.internal.commandline.AbstractCommand;
2627
import org.apache.ignite.internal.commandline.Command;
2728
import org.apache.ignite.internal.commandline.CommandArgIterator;
2829
import org.apache.ignite.internal.commandline.CommandLogger;
2930
import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskArg;
31+
import org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTaskResult;
3032

3133
import static org.apache.ignite.internal.commandline.CommandList.CONSISTENCY;
3234
import static org.apache.ignite.internal.commandline.TaskExecutor.BROADCAST_UUID;
@@ -46,25 +48,51 @@ public class ConsistencyCommand extends AbstractCommand<VisorConsistencyRepairTa
4648

4749
/** {@inheritDoc} */
4850
@Override public Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception {
51+
boolean failed = false;
52+
53+
StringBuilder sb = new StringBuilder();
54+
4955
try (GridClient client = Command.startClient(clientCfg)) {
50-
Object res = executeTaskByNameOnNode(
56+
VisorConsistencyRepairTaskResult res = executeTaskByNameOnNode(
5157
client,
5258
cmd.taskName(),
5359
arg(),
5460
BROADCAST_UUID,
5561
clientCfg
5662
);
5763

58-
log.info(String.valueOf(res));
64+
if (res.cancelled()) {
65+
sb.append("Operation execution cancelled.\n\n");
66+
67+
failed = true;
68+
}
69+
70+
if (res.failed()) {
71+
sb.append("Operation execution failed.\n\n");
72+
73+
failed = true;
74+
}
5975

60-
return res;
76+
if (failed)
77+
sb.append("[EXECUTION FAILED OR CANCELLED, RESULTS MAY BE INCOMPLETE OR INCONSISTENT]\n\n");
78+
79+
sb.append(res.message());
6180
}
6281
catch (Throwable e) {
6382
log.severe("Failed to perform operation.");
6483
log.severe(CommandLogger.errorMessage(e));
6584

6685
throw e;
6786
}
87+
88+
String output = sb.toString();
89+
90+
if (failed)
91+
throw new IgniteCheckedException(output);
92+
else
93+
log.info(output);
94+
95+
return output;
6896
}
6997

7098
/** {@inheritDoc} */

modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/query/KillCommand.java

Lines changed: 29 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
import org.apache.ignite.internal.util.typedef.T2;
3131
import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTask;
3232
import org.apache.ignite.internal.visor.compute.VisorComputeCancelSessionTaskArg;
33+
import org.apache.ignite.internal.visor.consistency.VisorConsistencyCancelTask;
3334
import org.apache.ignite.internal.visor.query.VisorContinuousQueryCancelTask;
3435
import org.apache.ignite.internal.visor.query.VisorContinuousQueryCancelTaskArg;
3536
import org.apache.ignite.internal.visor.query.VisorQueryCancelOnInitiatorTask;
@@ -51,6 +52,7 @@
5152
import static java.util.Collections.singletonMap;
5253
import static org.apache.ignite.internal.QueryMXBeanImpl.EXPECTED_GLOBAL_QRY_ID_FORMAT;
5354
import static org.apache.ignite.internal.commandline.CommandList.KILL;
55+
import static org.apache.ignite.internal.commandline.TaskExecutor.BROADCAST_UUID;
5456
import static org.apache.ignite.internal.commandline.TaskExecutor.executeTaskByNameOnNode;
5557
import static org.apache.ignite.internal.commandline.query.KillSubcommand.COMPUTE;
5658
import static org.apache.ignite.internal.commandline.query.KillSubcommand.CONTINUOUS;
@@ -77,14 +79,17 @@ public class KillCommand extends AbstractCommand<Object> {
7779
/** Task name. */
7880
private String taskName;
7981

82+
/** Node id. */
83+
private UUID nodeId;
84+
8085
/** {@inheritDoc} */
8186
@Override public Object execute(GridClientConfiguration clientCfg, Logger log) throws Exception {
8287
try (GridClient client = Command.startClient(clientCfg)) {
8388
return executeTaskByNameOnNode(
8489
client,
8590
taskName,
8691
taskArgs,
87-
null,
92+
nodeId,
8893
clientCfg
8994
);
9095
}
@@ -119,13 +124,17 @@ public class KillCommand extends AbstractCommand<Object> {
119124

120125
taskName = VisorComputeCancelSessionTask.class.getName();
121126

127+
nodeId = null;
128+
122129
break;
123130

124131
case SERVICE:
125132
taskArgs = new VisorCancelServiceTaskArg(argIter.nextArg("Expected service name."));
126133

127134
taskName = VisorCancelServiceTask.class.getName();
128135

136+
nodeId = null;
137+
129138
break;
130139

131140
case TRANSACTION:
@@ -136,6 +145,8 @@ public class KillCommand extends AbstractCommand<Object> {
136145

137146
taskName = VisorTxTask.class.getName();
138147

148+
nodeId = null;
149+
139150
break;
140151

141152
case SQL:
@@ -148,6 +159,8 @@ public class KillCommand extends AbstractCommand<Object> {
148159

149160
taskName = VisorQueryCancelOnInitiatorTask.class.getName();
150161

162+
nodeId = null;
163+
151164
break;
152165

153166
case SCAN:
@@ -163,6 +176,8 @@ public class KillCommand extends AbstractCommand<Object> {
163176

164177
taskName = VisorScanQueryCancelTask.class.getName();
165178

179+
nodeId = null;
180+
166181
break;
167182

168183
case CONTINUOUS:
@@ -172,13 +187,26 @@ public class KillCommand extends AbstractCommand<Object> {
172187

173188
taskName = VisorContinuousQueryCancelTask.class.getName();
174189

190+
nodeId = null;
191+
175192
break;
176193

177194
case SNAPSHOT:
178195
taskArgs = argIter.nextArg("Expected snapshot name.");
179196

180197
taskName = VisorSnapshotCancelTask.class.getName();
181198

199+
nodeId = null;
200+
201+
break;
202+
203+
case CONSISTENCY:
204+
taskName = VisorConsistencyCancelTask.class.getName();
205+
206+
taskArgs = null;
207+
208+
nodeId = BROADCAST_UUID;
209+
182210
break;
183211

184212
default:

modules/control-utility/src/main/java/org/apache/ignite/internal/commandline/query/KillSubcommand.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,7 @@ public enum KillSubcommand {
5454

5555
/** Kill snapshot operation. */
5656
SNAPSHOT,
57+
58+
/** Kill consistency tasks. */
59+
CONSISTENCY,
5760
}

modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerAbstractTest.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,7 @@
7373
import static org.apache.ignite.configuration.DataStorageConfiguration.DFLT_CHECKPOINT_FREQ;
7474
import static org.apache.ignite.configuration.EncryptionConfiguration.DFLT_REENCRYPTION_BATCH_SIZE;
7575
import static org.apache.ignite.configuration.EncryptionConfiguration.DFLT_REENCRYPTION_RATE_MBPS;
76+
import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION;
7677
import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PASSWORD;
7778
import static org.apache.ignite.internal.encryption.AbstractEncryptionTest.KEYSTORE_PATH;
7879
import static org.apache.ignite.internal.processors.cache.verify.VerifyBackupPartitionsDumpTask.IDLE_DUMP_FILE_PREFIX;
@@ -250,6 +251,8 @@ protected boolean idleVerifyRes(Path p) {
250251

251252
cfg.setDaemon(igniteInstanceName.startsWith(DAEMON_NODE_NAME_PREFIX));
252253

254+
cfg.setIncludeEventTypes(EVT_CONSISTENCY_VIOLATION); // Extend if necessary.
255+
253256
if (encryptionEnabled) {
254257
KeystoreEncryptionSpi encSpi = new KeystoreEncryptionSpi();
255258

modules/control-utility/src/test/java/org/apache/ignite/util/GridCommandHandlerConsistencyTest.java

Lines changed: 18 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@
4242
import static org.apache.ignite.cache.CacheAtomicityMode.TRANSACTIONAL;
4343
import static org.apache.ignite.events.EventType.EVT_CONSISTENCY_VIOLATION;
4444
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_OK;
45+
import static org.apache.ignite.internal.commandline.CommandHandler.EXIT_CODE_UNEXPECTED_ERROR;
4546
import static org.apache.ignite.internal.visor.consistency.VisorConsistencyRepairTask.CONSISTENCY_VIOLATIONS_FOUND;
4647
import static org.apache.ignite.testframework.GridTestUtils.assertContains;
4748

@@ -168,14 +169,29 @@ public void testCacheFilter() throws Exception {
168169
assertEquals(0, brokenParts.get());
169170
}
170171

172+
/**
173+
*
174+
*/
175+
@Test
176+
public void testRepairNonExistentCache() throws Exception {
177+
startGrids(3);
178+
179+
injectTestSystemOut();
180+
181+
for (int i = 0; i < PARTITIONS; i++) {
182+
assertEquals(EXIT_CODE_UNEXPECTED_ERROR, execute("--consistency", "repair", "non-existent", String.valueOf(i)));
183+
assertContains(log, testOut.toString(), "Cache not found");
184+
}
185+
}
186+
171187
/**
172188
*
173189
*/
174190
private void readRepairTx(AtomicInteger brokenParts, String cacheName) {
175191
for (int i = 0; i < PARTITIONS; i++) {
176192
assertEquals(EXIT_CODE_OK, execute("--consistency", "repair", cacheName, String.valueOf(i)));
177193
assertContains(log, testOut.toString(), CONSISTENCY_VIOLATIONS_FOUND);
178-
assertContains(log, testOut.toString(), "[found=1, fixed=1]");
194+
assertContains(log, testOut.toString(), "[found=1, fixed=1");
179195

180196
assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify"));
181197

@@ -196,7 +212,7 @@ private void readRepaitAtomic(AtomicInteger brokenParts, String cacheName) {
196212
for (int i = 0; i < PARTITIONS; i++) { // This may be a copy of previous (tx case), implement atomic repair to make this happen :)
197213
assertEquals(EXIT_CODE_OK, execute("--consistency", "repair", cacheName, String.valueOf(i)));
198214
assertContains(log, testOut.toString(), CONSISTENCY_VIOLATIONS_FOUND);
199-
assertContains(log, testOut.toString(), "[found=1, fixed=0]"); // Nothing fixed.
215+
assertContains(log, testOut.toString(), "[found=1, fixed=0"); // Nothing fixed.
200216

201217
assertEquals(EXIT_CODE_OK, execute("--cache", "idle_verify"));
202218
assertContains(log, testOut.toString(),

0 commit comments

Comments
 (0)