henrybear327 commented on code in PR #10934:
URL: https://github.com/apache/ozone/pull/10934#discussion_r3894178198


##########
hadoop-ozone/tools/src/main/java/org/apache/hadoop/ozone/local/LocalOzoneCluster.java:
##########
@@ -381,6 +390,141 @@ private void configureLocalDefaults(OzoneConfiguration 
conf) {
     conf.setFromObject(scmClientConfig);
   }
 
+  /**
+   * Applies a value the local runtime requires, rejecting a conflicting one 
the user configured.
+   * These keys are set rather than {@code setIfUnset} because 
ozone-default.xml would otherwise
+   * win; a user value is refused rather than replaced, so the cluster never 
behaves differently
+   * from the configuration the user is reading. Rejecting here, at the point 
of the override,
+   * keeps a later override from being added without the same check.
+   *
+   * <p>This overload compares text, for keys whose value carries no other 
spelling. The typed
+   * overloads below compare through the accessor the services read the key 
with, so a value that
+   * already means what the runtime requires is kept rather than rejected.</p>
+   *
+   * @throws IOException if the user configured {@code key} with a value other 
than {@code value}
+   */
+  private void setLocalOverride(OzoneConfiguration conf, String key, String 
value)
+      throws IOException {
+    // Configuration#unset() leaves the key in updatingResource, so a source 
can outlive its
+    // value; there is nothing to reject when no value is configured.
+    if (conf.get(key) != null && !value.equals(conf.get(key))) {
+      rejectUserConfigured(conf, key, value);
+    }
+    conf.set(key, value);
+  }
+
+  private void setLocalOverride(OzoneConfiguration conf, String key, boolean 
value)
+      throws IOException {
+    // Defaulting to the negation keeps a value getBoolean() cannot read from 
matching by accident.
+    if (conf.get(key) != null && conf.getBoolean(key, !value) != value) {
+      rejectUserConfigured(conf, key, String.valueOf(value));
+    }
+    conf.setBoolean(key, value);
+  }
+
+  private void setLocalOverride(OzoneConfiguration conf, String key, int value)
+      throws IOException {
+    if (conf.get(key) != null && !matchesInt(conf, key, value)) {
+      rejectUserConfigured(conf, key, String.valueOf(value));
+    }
+    conf.setInt(key, value);
+  }
+
+  /**
+   * Applies a duration the local runtime requires. The configured value is 
compared as a duration
+   * rather than as text, so the same length written in another unit is not 
treated as a conflict.
+   *
+   * @throws IOException if the user configured {@code key} with a different 
duration
+   */
+  private void setLocalOverrideDuration(OzoneConfiguration conf, String key, 
String value)
+      throws IOException {
+    long requiredMillis = TimeDurationUtil.getTimeDurationHelper(key, value, 
TimeUnit.MILLISECONDS);
+    if (conf.get(key) != null && !matchesDuration(conf, key, requiredMillis)) {
+      rejectUserConfigured(conf, key, value);
+    }
+    conf.set(key, value);
+  }
+
+  /**
+   * Applies a replication factor the local runtime requires, reading the 
configured value the way
+   * {@link org.apache.hadoop.hdds.client.ReplicationConfig#parse} does, which 
accepts both the
+   * numeric and the named spelling.
+   *
+   * @throws IOException if the user configured {@code key} with a different 
factor
+   */
+  private void setLocalOverrideReplication(OzoneConfiguration conf, String key,
+      ReplicationFactor value) throws IOException {
+    String configured = conf.get(key);
+    if (configured != null && parseReplicationFactor(configured) != value) {
+      rejectUserConfigured(conf, key, value.name());
+    }
+    conf.set(key, value.name());
+  }
+
+  /**
+   * Throws when the value {@code conf} carries for {@code key} is the user's 
choice rather than a
+   * shipped default. The message names the source because the user has to 
find the value to
+   * remove it.
+   */
+  private static void rejectUserConfigured(OzoneConfiguration conf, String 
key, String required)
+      throws IOException {
+    String source = userConfiguredSource(conf, key);
+    if (source != null) {
+      throw new IOException("ozone local requires " + key + "=" + required
+          + ", but the configuration sets " + conf.get(key) + " (source: " + 
source
+          + "). Remove that value, or run with a configuration directory 
(OZONE_CONF_DIR)"
+          + " that does not set it.");
+    }
+  }
+
+  private static boolean matchesInt(OzoneConfiguration conf, String key, int 
value) {
+    try {
+      return conf.getInt(key, value) == value;
+    } catch (NumberFormatException unreadable) {
+      // A value the accessor cannot read is a conflict; the caller reports it 
by key.
+      return false;
+    }
+  }
+
+  private static boolean matchesDuration(OzoneConfiguration conf, String key,
+      long requiredMillis) {
+    try {
+      return conf.getTimeDuration(key, requiredMillis, TimeUnit.MILLISECONDS) 
== requiredMillis;
+    } catch (NumberFormatException unreadable) {
+      return false;
+    }
+  }
+
+  /** Returns the factor {@code value} names in either spelling, or null if it 
names neither. */
+  private static ReplicationFactor parseReplicationFactor(String value) {
+    String trimmed = value.trim();
+    try {
+      return ReplicationFactor.valueOf(Integer.parseInt(trimmed));
+    } catch (IllegalArgumentException notNumeric) {
+      try {
+        return ReplicationFactor.valueOf(trimmed);
+      } catch (IllegalArgumentException notNamed) {
+        return null;
+      }
+    }
+  }
+
+  /**
+   * Returns where {@code key} got the value the user chose, or null if the 
user chose none. A
+   * value whose last source is the shipped ozone-default.xml is a default, 
not a user choice.
+   * The comparison is exact: Configuration records a classpath resource by 
its bare name, so a
+   * file the user named with {@code --conf} keeps its path here and stays a 
user choice however
+   * that file is called.
+   */
+  private static String userConfiguredSource(OzoneConfiguration conf, String 
key) {
+    String[] sources = conf.getPropertySources(key);
+    if (sources == null || sources.length == 0) {
+      return null;
+    }
+    String source = sources[sources.length - 1];
+    return OZONE_DEFAULT_XML.equals(source) ? null : source;

Review Comment:
   the implementation now derives all *-default.xml names from 
OzoneConfiguration.getConfigurationResourceFiles() 
   



-- 
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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]

Reply via email to