keith-turner commented on code in PR #6040:
URL: https://github.com/apache/accumulo/pull/6040#discussion_r2721813502
##########
core/src/main/java/org/apache/accumulo/core/iteratorsImpl/IteratorConfigUtil.java:
##########
@@ -273,4 +295,216 @@ private static Class<SortedKeyValueIterator<Key,Value>>
loadClass(boolean useAcc
log.trace("Iterator class {} loaded from classpath", iterInfo.className);
return clazz;
}
+
+ public static void checkIteratorConflicts(Map<String,String> props, String
property, String value)
+ throws AccumuloException {
+ if (props.containsKey(property) && props.get(property).equals(value)) {
+ // setting a property that already exists (i.e., no change)
+ return;
+ }
+ if (isNonOptionIterProp(property, value)) {
+ String[] iterPropParts = property.split("\\.");
+ IteratorScope scope = IteratorScope.valueOf(iterPropParts[2]);
+ String iterName = iterPropParts[3];
+ String[] priorityAndClass;
+ if ((priorityAndClass = value.split(",")).length == 2) {
+ // given a single property, the only way for the property to be
equivalent to an existing
+ // iterator is if the existing iterator has no options (opts are set
as separate props)
+ IteratorSetting givenIter = new
IteratorSetting(Integer.parseInt(priorityAndClass[0]),
+ iterName, priorityAndClass[1]);
+ checkIteratorConflicts(props, givenIter, EnumSet.of(scope), false);
+ }
+ }
+ }
+
+ public static void checkIteratorConflicts(TableOperations tableOps,
NamespaceOperationsHelper noh,
+ String namespace, String property, String value)
+ throws AccumuloException, AccumuloSecurityException,
NamespaceNotFoundException {
+ var props = noh.getNamespaceProperties(namespace);
+ if (props.containsKey(property) && props.get(property).equals(value)) {
+ // setting a property that already exists (i.e., no change)
+ return;
+ }
+
+ // checking for conflicts in the namespace
+ if (isNonOptionIterProp(property, value)) {
+ String[] iterPropParts = property.split("\\.");
+ IteratorScope scope = IteratorScope.valueOf(iterPropParts[2]);
+ String iterName = iterPropParts[3];
+ String[] priorityAndClass;
+ if ((priorityAndClass = value.split(",")).length == 2) {
+ // given a single property, the only way for the property to be
equivalent to an existing
+ // iterator is if the existing iterator has no options (opts are set
as separate props)
+ IteratorSetting givenIter = new
IteratorSetting(Integer.parseInt(priorityAndClass[0]),
+ iterName, priorityAndClass[1]);
+ checkIteratorConflicts(props, givenIter, EnumSet.of(scope), false);
+ }
+ }
+
+ // checking for conflicts for the tables in the namespace
+ checkIteratorConflictsWithTablesInNamespace(tableOps, namespace, property,
value);
+ }
+
+ public static void
checkIteratorConflictsWithTablesInNamespace(TableOperations tableOps,
+ String namespace, IteratorSetting is, EnumSet<IteratorScope> scopes)
+ throws AccumuloException {
+ Set<String> tablesInNamespace;
+ if (namespace.equals(Namespace.DEFAULT.name())) {
+ tablesInNamespace = tableOps.list().stream().filter(t ->
!t.contains(Namespace.SEPARATOR))
+ .collect(Collectors.toSet());
+ } else {
+ tablesInNamespace = tableOps.list().stream()
+ .filter(t -> t.startsWith(namespace +
Namespace.SEPARATOR)).collect(Collectors.toSet());
+ }
+ try {
+ for (var table : tablesInNamespace) {
+ checkIteratorConflicts(tableOps.getTableProperties(table), is, scopes,
false);
+ }
+ } catch (TableNotFoundException e) {
+ throw new AccumuloException(e);
+ }
+ }
+
+ public static void
checkIteratorConflictsWithTablesInNamespace(TableOperations tableOps,
+ String namespace, String property, String value) throws
AccumuloException {
+ Set<String> tablesInNamespace;
+ if (namespace.equals(Namespace.DEFAULT.name())) {
+ tablesInNamespace = tableOps.list().stream().filter(t ->
!t.contains(Namespace.SEPARATOR))
+ .collect(Collectors.toSet());
+ } else {
+ tablesInNamespace = tableOps.list().stream()
+ .filter(t -> t.startsWith(namespace +
Namespace.SEPARATOR)).collect(Collectors.toSet());
+ }
+ try {
+ for (var table : tablesInNamespace) {
+ checkIteratorConflicts(tableOps.getTableProperties(table), property,
value);
+ }
+ } catch (TableNotFoundException e) {
+ throw new AccumuloException(e);
+ }
+ }
+
+ public static void checkIteratorConflicts(IteratorSetting iterToCheck,
+ EnumSet<IteratorScope> iterScopesToCheck,
+ Map<IteratorScope,List<IteratorSetting>> existingIters, boolean
shouldThrow)
+ throws AccumuloException {
+ // The reason for the 'shouldThrow' var is to prevent newly added 2.x
checks from breaking
+ // existing user code. Just log the problem and proceed. Major version > 2
will always throw
+ for (var scope : iterScopesToCheck) {
+ var existingItersForScope = existingIters.get(scope);
+ if (existingItersForScope == null) {
+ continue;
+ }
+ for (var existingIter : existingItersForScope) {
+ // not a conflict if exactly the same
+ if (iterToCheck.equals(existingIter)) {
+ continue;
+ }
+ if (iterToCheck.getName().equals(existingIter.getName())) {
+ String msg =
+ String.format("iterator name conflict at %s scope. %s conflicts
with existing %s",
+ scope, iterToCheck, existingIter);
+ if (shouldThrow) {
+ throw new AccumuloException(new IllegalArgumentException(msg));
+ } else {
+ log.warn(msg + WARNING_MSG);
+ }
+ }
+ if (iterToCheck.getPriority() == existingIter.getPriority()) {
+ String msg =
+ String.format("iterator priority conflict at %s scope. %s
conflicts with existing %s",
+ scope, iterToCheck, existingIter);
+ if (shouldThrow) {
+ throw new AccumuloException(new IllegalArgumentException(msg));
+ } else {
+ log.warn(msg + WARNING_MSG);
+ }
+ }
+ }
+ }
+ }
+
+ public static void checkIteratorConflicts(Map<String,String> props,
IteratorSetting iterToCheck,
Review Comment:
Created #6074
--
This is an automated message from the Apache Git Service.
To respond to the message, please log on to GitHub and use the
URL above to go to the specific comment.
To unsubscribe, e-mail: [email protected]
For queries about this service, please contact Infrastructure at:
[email protected]