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]

Reply via email to