Skip to content

Commit

Permalink
IGNITE-20418 Added the multiple nodes argument to the 'indexes_force_…
Browse files Browse the repository at this point in the history
…rebuild' command (#10941)
  • Loading branch information
Vladsz83 authored Sep 29, 2023
1 parent 66bd852 commit fc8a07e
Show file tree
Hide file tree
Showing 11 changed files with 612 additions and 76 deletions.
4 changes: 2 additions & 2 deletions docs/_docs/tools/control-script.adoc
Original file line number Diff line number Diff line change
Expand Up @@ -1071,12 +1071,12 @@ To trigger the rebuild process of all indexes for the specified caches or the ca
tab:Unix[]
[source,shell]
----
control.sh --cache indexes_force_rebuild --node-id nodeId --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN
control.sh --cache indexes_force_rebuild --node-ids nodeId1,...nodeIdN|--all-nodes --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN
----
tab:Window[]
[source,shell]
----
control.bat --cache indexes_force_rebuild --node-id nodeId --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN
control.bat --cache indexes_force_rebuild --node-ids nodeId1,...nodeIdN|--all-nodes --cache-names cacheName1,...cacheNameN|--group-names groupName1,...groupNameN
----
--

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -21,8 +21,6 @@
import java.lang.reflect.Field;
import java.util.ArrayDeque;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Deque;
import java.util.HashSet;
import java.util.Iterator;
Expand All @@ -42,6 +40,7 @@
import org.apache.ignite.internal.management.api.ArgumentGroup;
import org.apache.ignite.internal.management.api.CliSubcommandsWithPrefix;
import org.apache.ignite.internal.management.api.Command;
import org.apache.ignite.internal.management.api.CommandUtils;
import org.apache.ignite.internal.management.api.CommandsRegistry;
import org.apache.ignite.internal.management.api.Positional;
import org.apache.ignite.internal.util.typedef.internal.U;
Expand Down Expand Up @@ -350,13 +349,11 @@ private CLIArgumentParser createArgumentParser() {
(name, val) -> {}
);

ArgumentGroup argGrp = cmdPath.peek().argClass().getAnnotation(ArgumentGroup.class);
Set<String> grpdFlds = argGrp == null
? Collections.emptySet()
: new HashSet<>(Arrays.asList(argGrp.value()));
List<Set<String>> grpdFlds = CommandUtils.argumentGroupsValues(cmdPath.peek().argClass());

Consumer<Field> namedArgCb = fld -> namedArgs.add(
toArg.apply(fld, grpdFlds.contains(fld.getName()) || fld.getAnnotation(Argument.class).optional())
toArg.apply(fld, CommandUtils.argumentGroupIdx(grpdFlds, fld.getName()) >= 0
|| fld.getAnnotation(Argument.class).optional())
);

Consumer<Field> positionalArgCb = fld -> positionalArgs.add(new CLIArgument<>(
Expand Down

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
package org.apache.ignite.internal.management.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
Expand All @@ -28,9 +29,11 @@
* If values from {@link #value()} not conform restrictions then error will be thrown.
*
* @see org.apache.ignite.internal.management.SystemViewCommandArg
* @see ArgumentGroupsHolder
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.TYPE)
@Repeatable(ArgumentGroupsHolder.class)
public @interface ArgumentGroup {
/** @return Names of argument class fields to forms "group" restriction. */
public String[] value();
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
/*
* 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.management.api;

import java.lang.annotation.ElementType;
import java.lang.annotation.Repeatable;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

/**
* {@link Repeatable} container for {@link ArgumentGroup}.
*/
@Retention(RetentionPolicy.RUNTIME)
@Target({ElementType.TYPE})
public @interface ArgumentGroupsHolder {
/** Array of {@link ArgumentGroup} annotations. */
ArgumentGroup[] value();
}
Original file line number Diff line number Diff line change
Expand Up @@ -369,21 +369,27 @@ public static <A extends IgniteDataTransferObject> void visitCommandParams(
List<Field> positionalParams = new ArrayList<>();
List<Field> namedParams = new ArrayList<>();

ArgumentGroup argGrp = argCls.getAnnotation(ArgumentGroup.class);
List<ArgumentGroup> argGprs = argumentGroups(argCls);

Set<String> grpNames = argGrp != null
? new HashSet<>(Arrays.asList(argGrp.value()))
: Collections.emptySet();
List<Set<String>> grpNames = argumentGroupsValues(argGprs);

List<Field> grpFlds = new ArrayList<>();
List<List<Field>> grpFlds = grpNames.isEmpty() ? Collections.emptyList() : new ArrayList<>(grpNames.size());

grpNames.forEach(gf -> grpFlds.add(grpFlds.size(), null));

// Iterates classes from the roots.
for (int i = classes.size() - 1; i >= 0; i--) {
Field[] flds = classes.get(i).getDeclaredFields();

for (Field fld : flds) {
if (grpNames.contains(fld.getName()))
grpFlds.add(fld);
int argGrpIdx = argumentGroupIdx(grpNames, fld.getName());

if (argGrpIdx >= 0) {
if (grpFlds.get(argGrpIdx) == null)
grpFlds.set(argGrpIdx, new ArrayList<>());

grpFlds.get(argGrpIdx).add(fld);
}
else if (fld.isAnnotationPresent(Positional.class))
positionalParams.add(fld);
else if (fld.isAnnotationPresent(Argument.class))
Expand All @@ -395,8 +401,61 @@ else if (fld.isAnnotationPresent(Argument.class))

namedParams.forEach(namedParamVisitor);

if (argGrp != null)
argumentGroupVisitor.accept(argGrp, grpFlds);
for (int i = 0; i < grpFlds.size(); ++i)
argumentGroupVisitor.accept(argGprs.get(i), grpFlds.get(i));
}

/**
* @return List of declared {@link ArgumentGroup} at {@code cls}. Singleton list if only one argument group is
* declared. Empty list if no argument group is declared.
*/
private static List<ArgumentGroup> argumentGroups(Class<?> cls) {
ArgumentGroup singleGrp = cls.getAnnotation(ArgumentGroup.class);

if (singleGrp != null) {
assert cls.getAnnotation(ArgumentGroupsHolder.class) == null;

return Collections.singletonList(singleGrp);
}

ArgumentGroupsHolder grps = cls.getAnnotation(ArgumentGroupsHolder.class);

return grps == null ? Collections.emptyList() : Arrays.asList(grps.value());
}

/**
* @return Sets list of {@link ArgumentGroup#value()} declared at {@code cls}.
*/
public static List<Set<String>> argumentGroupsValues(Class<?> cls) {
return argumentGroupsValues(argumentGroups(cls));
}

/**
* @return Sets list of {@link ArgumentGroup#value()} holding in {@code argGrps}.
* @see #argumentGroupsValues(Class)
*/
public static List<Set<String>> argumentGroupsValues(List<ArgumentGroup> argGrps) {
List<Set<String>> res = argGrps.stream().map(grp -> new HashSet<>(Arrays.asList(grp.value())))
.collect(Collectors.toList());

// Checks that argument groups only unique values.
assert F.flatCollections(res).stream().collect(Collectors.groupingBy(Function.identity(), Collectors.counting()))
.entrySet().stream().noneMatch(e -> e.getValue() > 1) : "Argument groups " + argGrps + " have not unique arguments";

return res;
}

/**
* @return Index of first value set in {@code argGrpValues} containing {@code name}. -1 if not found.
* @see #argumentGroupsValues(Class)
*/
public static int argumentGroupIdx(List<Set<String>> argGrpValues, String name) {
for (int i = 0; i < argGrpValues.size(); ++i) {
if (argGrpValues.get(i).contains(name))
return i;
}

return -1;
}

/**
Expand Down Expand Up @@ -690,8 +749,12 @@ public static <A extends IgniteDataTransferObject> A argument(
})
);

if (arg.argGrp != null && (!arg.grpOptional() && !arg.grpFldExists))
throw new IllegalArgumentException("One of " + toFormattedNames(argCls, arg.grpdFlds) + " required");
for (int grpIdx = 0; grpIdx < arg.argGrps.size(); ++grpIdx) {
if (!arg.argGrps.get(grpIdx).optional() && !arg.grpFldExists[grpIdx]) {
throw new IllegalArgumentException("One of " + toFormattedNames(argCls, arg.grpdFlds.get(grpIdx))
+ " required");
}
}

return arg.res;
}
Expand Down Expand Up @@ -737,32 +800,29 @@ public static <A, R> R execute(
/** */
private static class ArgumentState<A extends IgniteDataTransferObject> implements BiConsumer<Field, Object> {
/** */
final A res;
private final A res;

/** */
final ArgumentGroup argGrp;
private final List<ArgumentGroup> argGrps;

/** */
boolean grpFldExists;
private final @Nullable boolean[] grpFldExists;

/** */
int idx;
private int idx;

/** */
final Set<String> grpdFlds;
private final List<Set<String>> grpdFlds;

/** */
public ArgumentState(Class<A> argCls) throws InstantiationException, IllegalAccessException {
res = argCls.newInstance();
argGrp = argCls.getAnnotation(ArgumentGroup.class);
grpdFlds = argGrp == null
? Collections.emptySet()
: new HashSet<>(Arrays.asList(argGrp.value()));
}

/** */
public boolean grpOptional() {
return argGrp == null || argGrp.optional();
argGrps = argumentGroups(argCls);

grpdFlds = argumentGroupsValues(argGrps);

grpFldExists = argGrps.isEmpty() ? null : new boolean[argGrps.size()];
}

/** */
Expand All @@ -776,10 +836,14 @@ private int nextIdx() {

/** {@inheritDoc} */
@Override public void accept(Field fld, Object val) {
boolean grpdFld = grpdFlds.contains(fld.getName());
int argGrpIdx = argumentGroupIdx(grpdFlds, fld.getName());

assert argGrpIdx < argGrps.size();

ArgumentGroup argGrp = argGrpIdx < 0 ? null : argGrps.get(argGrpIdx);

if (val == null) {
if (grpdFld || fld.getAnnotation(Argument.class).optional())
if (argGrp != null || fld.getAnnotation(Argument.class).optional())
return;

String name = fld.isAnnotationPresent(Positional.class)
Expand All @@ -792,14 +856,16 @@ private int nextIdx() {
if (Objects.equals(val, get(fld)))
return;

if (grpdFld) {
if (grpFldExists && (argGrp != null && argGrp.onlyOneOf())) {
if (argGrp != null) {
assert grpFldExists != null;

if (grpFldExists[argGrpIdx] && argGrp.onlyOneOf()) {
throw new IllegalArgumentException(
"Only one of " + toFormattedNames(res.getClass(), grpdFlds) + " allowed"
"Only one of " + toFormattedNames(res.getClass(), grpdFlds.get(argGrpIdx)) + " allowed"
);
}

grpFldExists = true;
grpFldExists[argGrpIdx] = true;
}

set(fld, val);
Expand Down
Loading

0 comments on commit fc8a07e

Please sign in to comment.