You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@iceberg.apache.org by ja...@apache.org on 2021/12/03 02:15:22 UTC

[iceberg] branch master updated: Core: ensure MetricsConfig is immutable (#3638)

This is an automated email from the ASF dual-hosted git repository.

jackye pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/iceberg.git


The following commit(s) were added to refs/heads/master by this push:
     new df5a5f1  Core: ensure MetricsConfig is immutable (#3638)
df5a5f1 is described below

commit df5a5f15997ac8035a23731ed6a3660e60f1d781
Author: Piotr Findeisen <pi...@gmail.com>
AuthorDate: Fri Dec 3 03:15:15 2021 +0100

    Core: ensure MetricsConfig is immutable (#3638)
---
 .../java/org/apache/iceberg/MetricsConfig.java     | 50 +++++++++++++---------
 .../main/java/org/apache/iceberg/MetricsModes.java |  5 +++
 2 files changed, 34 insertions(+), 21 deletions(-)

diff --git a/core/src/main/java/org/apache/iceberg/MetricsConfig.java b/core/src/main/java/org/apache/iceberg/MetricsConfig.java
index bf8122f..4dc956a 100644
--- a/core/src/main/java/org/apache/iceberg/MetricsConfig.java
+++ b/core/src/main/java/org/apache/iceberg/MetricsConfig.java
@@ -23,9 +23,11 @@ import java.io.Serializable;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
+import javax.annotation.concurrent.Immutable;
 import org.apache.iceberg.MetricsModes.MetricsMode;
 import org.apache.iceberg.exceptions.ValidationException;
 import org.apache.iceberg.relocated.com.google.common.base.Joiner;
+import org.apache.iceberg.relocated.com.google.common.collect.ImmutableMap;
 import org.apache.iceberg.relocated.com.google.common.collect.Maps;
 import org.apache.iceberg.util.SortOrderUtil;
 import org.slf4j.Logger;
@@ -35,21 +37,25 @@ import static org.apache.iceberg.TableProperties.DEFAULT_WRITE_METRICS_MODE;
 import static org.apache.iceberg.TableProperties.DEFAULT_WRITE_METRICS_MODE_DEFAULT;
 import static org.apache.iceberg.TableProperties.METRICS_MODE_COLUMN_CONF_PREFIX;
 
-public class MetricsConfig implements Serializable {
+@Immutable
+public final class MetricsConfig implements Serializable {
 
   private static final Logger LOG = LoggerFactory.getLogger(MetricsConfig.class);
   private static final Joiner DOT = Joiner.on('.');
 
-  private Map<String, MetricsMode> columnModes = Maps.newHashMap();
-  private MetricsMode defaultMode;
+  private static final MetricsConfig DEFAULT = new MetricsConfig(ImmutableMap.of(),
+          MetricsModes.fromString(DEFAULT_WRITE_METRICS_MODE_DEFAULT));
 
-  private MetricsConfig() {
+  private final Map<String, MetricsMode> columnModes;
+  private final MetricsMode defaultMode;
+
+  private MetricsConfig(Map<String, MetricsMode> columnModes, MetricsMode defaultMode) {
+    this.columnModes = ImmutableMap.copyOf(columnModes);
+    this.defaultMode = defaultMode;
   }
 
   public static MetricsConfig getDefault() {
-    MetricsConfig spec = new MetricsConfig();
-    spec.defaultMode = MetricsModes.fromString(DEFAULT_WRITE_METRICS_MODE_DEFAULT);
-    return spec;
+    return DEFAULT;
   }
 
   static Map<String, String> updateProperties(Map<String, String> props, List<String> deletedColumns,
@@ -104,38 +110,40 @@ public class MetricsConfig implements Serializable {
    * @param table an Iceberg table
    */
   public static MetricsConfig forPositionDelete(Table table) {
-    MetricsConfig config = new MetricsConfig();
+    ImmutableMap.Builder<String, MetricsMode> columnModes = ImmutableMap.builder();
 
-    config.columnModes.put(MetadataColumns.DELETE_FILE_PATH.name(), MetricsModes.Full.get());
-    config.columnModes.put(MetadataColumns.DELETE_FILE_POS.name(), MetricsModes.Full.get());
+    columnModes.put(MetadataColumns.DELETE_FILE_PATH.name(), MetricsModes.Full.get());
+    columnModes.put(MetadataColumns.DELETE_FILE_POS.name(), MetricsModes.Full.get());
 
     MetricsConfig tableConfig = forTable(table);
 
-    config.defaultMode = tableConfig.defaultMode;
+    MetricsMode defaultMode = tableConfig.defaultMode;
     tableConfig.columnModes.forEach((columnAlias, mode) -> {
       String positionDeleteColumnAlias = DOT.join(MetadataColumns.DELETE_FILE_ROW_FIELD_NAME, columnAlias);
-      config.columnModes.put(positionDeleteColumnAlias, mode);
+      columnModes.put(positionDeleteColumnAlias, mode);
     });
 
-    return config;
+    return new MetricsConfig(columnModes.build(), defaultMode);
   }
 
   private static MetricsConfig from(Map<String, String> props, SortOrder order) {
-    MetricsConfig spec = new MetricsConfig();
+    Map<String, MetricsMode> columnModes = Maps.newHashMap();
+    MetricsMode defaultMode;
     String defaultModeAsString = props.getOrDefault(DEFAULT_WRITE_METRICS_MODE, DEFAULT_WRITE_METRICS_MODE_DEFAULT);
     try {
-      spec.defaultMode = MetricsModes.fromString(defaultModeAsString);
+      defaultMode = MetricsModes.fromString(defaultModeAsString);
     } catch (IllegalArgumentException err) {
       // Mode was invalid, log the error and use the default
       LOG.warn("Ignoring invalid default metrics mode: {}", defaultModeAsString, err);
-      spec.defaultMode = MetricsModes.fromString(DEFAULT_WRITE_METRICS_MODE_DEFAULT);
+      defaultMode = MetricsModes.fromString(DEFAULT_WRITE_METRICS_MODE_DEFAULT);
     }
 
     // First set sorted column with sorted column default (can be overridden by user)
-    MetricsMode sortedColDefaultMode = sortedColumnDefaultMode(spec.defaultMode);
+    MetricsMode sortedColDefaultMode = sortedColumnDefaultMode(defaultMode);
     Set<String> sortedCols = SortOrderUtil.orderPreservingSortedColumns(order);
-    sortedCols.forEach(sc -> spec.columnModes.put(sc, sortedColDefaultMode));
+    sortedCols.forEach(sc -> columnModes.put(sc, sortedColDefaultMode));
 
+    MetricsMode defaultModeFinal = defaultMode;
     props.keySet().stream()
         .filter(key -> key.startsWith(METRICS_MODE_COLUMN_CONF_PREFIX))
         .forEach(key -> {
@@ -146,12 +154,12 @@ public class MetricsConfig implements Serializable {
           } catch (IllegalArgumentException err) {
             // Mode was invalid, log the error and use the default
             LOG.warn("Ignoring invalid metrics mode for column {}: {}", columnAlias, props.get(key), err);
-            mode = spec.defaultMode;
+            mode = defaultModeFinal;
           }
-          spec.columnModes.put(columnAlias, mode);
+          columnModes.put(columnAlias, mode);
         });
 
-    return spec;
+    return new MetricsConfig(columnModes, defaultMode);
   }
 
   /**
diff --git a/core/src/main/java/org/apache/iceberg/MetricsModes.java b/core/src/main/java/org/apache/iceberg/MetricsModes.java
index cc805f7..8fea565 100644
--- a/core/src/main/java/org/apache/iceberg/MetricsModes.java
+++ b/core/src/main/java/org/apache/iceberg/MetricsModes.java
@@ -56,6 +56,11 @@ public class MetricsModes {
     throw new IllegalArgumentException("Invalid metrics mode: " + mode);
   }
 
+  /**
+   * A metrics calculation mode.
+   * <p>
+   * Implementations must be immutable.
+   */
   public interface MetricsMode extends Serializable {
   }