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

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


The following commit(s) were added to refs/heads/master by this push:
     new 897c610e650 HDDS-14126. Introduce builder for metadata map (#9474)
897c610e650 is described below

commit 897c610e65063fee85014494a18d9146170402d1
Author: Doroszlai, Attila <[email protected]>
AuthorDate: Fri Dec 12 21:28:21 2025 +0100

    HDDS-14126. Introduce builder for metadata map (#9474)
---
 .../main/java/org/apache/hadoop/ozone/OmUtils.java |   7 +-
 .../apache/hadoop/ozone/om/helpers/MapBuilder.java | 108 ++++++++++++++
 .../hadoop/ozone/om/helpers/OmBucketInfo.java      |   6 -
 .../hadoop/ozone/om/helpers/OmDirectoryInfo.java   |   6 -
 .../apache/hadoop/ozone/om/helpers/OmKeyInfo.java  |  10 --
 .../hadoop/ozone/om/helpers/OmVolumeArgs.java      |   6 -
 .../hadoop/ozone/om/helpers/WithMetadata.java      |  22 ++-
 .../hadoop/ozone/om/helpers/TestMapBuilder.java    | 160 +++++++++++++++++++++
 .../hadoop/ozone/om/helpers/TestOmVolumeArgs.java  |   4 +-
 .../hadoop/ozone/om/helpers/OmPrefixInfo.java      |   6 -
 .../hadoop/ozone/om/helpers/TestOmPrefixInfo.java  |   5 +-
 .../ozone/om/helpers/TestOmPrefixInfoCodec.java    |   3 +-
 .../S3MultipartUploadCompleteRequest.java          |   4 +-
 .../ozone/om/response/TestOMResponseUtils.java     |  14 +-
 .../hadoop/ozone/recon/api/NSSummaryTests.java     |   3 +-
 15 files changed, 302 insertions(+), 62 deletions(-)

diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
index 5f149ffcc96..240b6b89531 100644
--- a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
+++ b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/OmUtils.java
@@ -548,10 +548,9 @@ public static RepeatedOmKeyInfo prepareKeyForDelete(long 
bucketId, OmKeyInfo key
     if (Boolean.parseBoolean(
             keyInfo.getMetadata().get(OzoneConsts.GDPR_FLAG))
     ) {
-      Map<String, String> metadata = builder.getMetadata();
-      metadata.remove(OzoneConsts.GDPR_FLAG);
-      metadata.remove(OzoneConsts.GDPR_ALGORITHM);
-      metadata.remove(OzoneConsts.GDPR_SECRET);
+      builder.metadata().remove(OzoneConsts.GDPR_FLAG);
+      builder.metadata().remove(OzoneConsts.GDPR_ALGORITHM);
+      builder.metadata().remove(OzoneConsts.GDPR_SECRET);
     
       builder.setFileEncryptionInfo(null);
     }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/MapBuilder.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/MapBuilder.java
new file mode 100644
index 00000000000..7cc46db970f
--- /dev/null
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/MapBuilder.java
@@ -0,0 +1,108 @@
+/*
+ * 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.hadoop.ozone.om.helpers;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.Objects;
+
+/** Helps incrementally build an immutable map. */
+public final class MapBuilder<K, V> {
+  /** The original map being built from, used if no changes are made, to 
reduce copying. */
+  private final ImmutableMap<K, V> original;
+  /** The updated map being built, created lazily on the first modification. */
+  private Map<K, V> updated;
+  /** Whether any changes were made. */
+  private boolean changed;
+
+  public static <K, V> MapBuilder<K, V> empty() {
+    return new MapBuilder<>(ImmutableMap.of());
+  }
+
+  public static <K, V> MapBuilder<K, V> of(ImmutableMap<K, V> original) {
+    return new MapBuilder<>(original);
+  }
+
+  public static <K, V> MapBuilder<K, V> copyOf(Map<K, V> original) {
+    return new MapBuilder<>(ImmutableMap.copyOf(original));
+  }
+
+  private MapBuilder(ImmutableMap<K, V> original) {
+    this.original = original;
+  }
+
+  public void put(final K key, final V value) {
+    Objects.requireNonNull(key, "key == null");
+    Objects.requireNonNull(value, "value == null");
+
+    ensureInitialized();
+    V prev = updated.put(key, value);
+    changed |= prev != value;
+  }
+
+  public void putAll(final Map<? extends K, ? extends V> map) {
+    Objects.requireNonNull(map, "map == null");
+
+    if (!map.isEmpty()) {
+      ensureInitialized();
+      updated.putAll(map);
+      changed = true; // assume change instead of checking
+    }
+  }
+
+  public void remove(final K key) {
+    Objects.requireNonNull(key, "key == null");
+
+    if (updated == null && !original.containsKey(key)) {
+      return;
+    }
+
+    ensureInitialized();
+    V prev = updated.remove(key);
+    changed |= prev != null;
+  }
+
+  /** Set the map being built to {@code map}.
+   * For further mutations to work, it must be modifiable,
+   * but it can also be immutable if this is the last change. */
+  public void set(final Map<K, V> map) {
+    Objects.requireNonNull(map, "map == null");
+
+    updated = map;
+    changed = map != original; // assume change instead of deep checking 
equality
+  }
+
+  public boolean isChanged() {
+    return changed;
+  }
+
+  public ImmutableMap<K, V> build() {
+    return changed ? ImmutableMap.copyOf(updated) : original;
+  }
+
+  ImmutableMap<K, V> initialValue() {
+    return original;
+  }
+
+  private void ensureInitialized() {
+    if (updated == null) {
+      updated = new LinkedHashMap<>(original);
+    }
+  }
+}
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java
index b8d8f409894..89c9e717e4e 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmBucketInfo.java
@@ -484,12 +484,6 @@ public Builder setUpdateID(long id) {
       return this;
     }
 
-    @Override
-    public Builder addMetadata(String key, String value) {
-      super.addMetadata(key, value);
-      return this;
-    }
-
     @Override
     public Builder addAllMetadata(Map<String, String> additionalMetadata) {
       super.addAllMetadata(additionalMetadata);
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDirectoryInfo.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDirectoryInfo.java
index 01a1972c6aa..e584417f222 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDirectoryInfo.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmDirectoryInfo.java
@@ -141,12 +141,6 @@ public Builder addAcl(OzoneAcl ozoneAcl) {
       return this;
     }
 
-    @Override
-    public Builder addMetadata(String key, String value) {
-      super.addMetadata(key, value);
-      return this;
-    }
-
     @Override
     public Builder addAllMetadata(Map<String, String> additionalMetadata) {
       super.addAllMetadata(additionalMetadata);
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java
index 5e64b87f1c9..a600894f63b 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmKeyInfo.java
@@ -215,16 +215,6 @@ public OmKeyInfo withMetadataMutations(
     return toBuilder().setMetadata(metadataCopy).build();
   }
 
-  /**
-   * Returns a new {@link OmKeyInfo} with metadata replaced by the provided
-   * map.
-   * @param metadata the metadata to set
-   * @return a new {@link OmKeyInfo}
-   */
-  public OmKeyInfo withMetadata(Map<String, String> metadata) {
-    return toBuilder().setMetadata(metadata).build();
-  }
-
   public boolean isDeletedKeyCommitted() {
     return Boolean.parseBoolean(getMetadata().get(COMMITTED_KEY_DELETED_FLAG));
   }
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
index 26a7fe63bd3..aa519981129 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/OmVolumeArgs.java
@@ -307,12 +307,6 @@ public Builder incrUsedNamespace(long n) {
       return this;
     }
 
-    @Override
-    public Builder addMetadata(String key, String value) {
-      super.addMetadata(key, value);
-      return this;
-    }
-
     @Override
     public Builder addAllMetadata(Map<String, String> additionalMetaData) {
       super.addAllMetadata(additionalMetaData);
diff --git 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/WithMetadata.java
 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/WithMetadata.java
index ba3469a4405..ba319f4a2c8 100644
--- 
a/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/WithMetadata.java
+++ 
b/hadoop-ozone/common/src/main/java/org/apache/hadoop/ozone/om/helpers/WithMetadata.java
@@ -19,7 +19,6 @@
 
 import com.google.common.collect.ImmutableMap;
 import java.util.Map;
-import java.util.concurrent.ConcurrentHashMap;
 import net.jcip.annotations.Immutable;
 
 /**
@@ -28,39 +27,37 @@
 @Immutable
 public abstract class WithMetadata {
 
-  private final Map<String, String> metadata;
+  private final ImmutableMap<String, String> metadata;
 
   protected WithMetadata() {
     metadata = ImmutableMap.of();
   }
 
   protected WithMetadata(Builder b) {
-    metadata = b.metadata == null ? ImmutableMap.of()
-        : ImmutableMap.copyOf(b.metadata);
+    metadata = b.metadata.build();
   }
 
   protected WithMetadata(WithMetadata other) {
-    metadata = other.getMetadata() == null ? ImmutableMap.of()
-        : ImmutableMap.copyOf(other.getMetadata());
+    metadata = other.getMetadata();
   }
 
   /**
    * Custom key value metadata.
    */
-  public final Map<String, String> getMetadata() {
+  public final ImmutableMap<String, String> getMetadata() {
     return metadata;
   }
 
   /** Builder for {@link WithMetadata}. */
   public static class Builder {
-    private final Map<String, String> metadata;
+    private final MapBuilder<String, String> metadata;
 
     protected Builder() {
-      metadata = new ConcurrentHashMap<>();
+      metadata = MapBuilder.empty();
     }
 
     protected Builder(WithMetadata obj) {
-      metadata = new ConcurrentHashMap<>(obj.getMetadata());
+      metadata = MapBuilder.of(obj.getMetadata());
     }
 
     public Builder addMetadata(String key, String value) {
@@ -76,12 +73,11 @@ public Builder addAllMetadata(Map<String, String> 
additionalMetadata) {
     }
 
     public Builder setMetadata(Map<String, String> map) {
-      metadata.clear();
-      addAllMetadata(map);
+      metadata.set(map);
       return this;
     }
 
-    public Map<String, String> getMetadata() {
+    public MapBuilder<String, String> metadata() {
       return metadata;
     }
   }
diff --git 
a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestMapBuilder.java
 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestMapBuilder.java
new file mode 100644
index 00000000000..19e2da32b16
--- /dev/null
+++ 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestMapBuilder.java
@@ -0,0 +1,160 @@
+/*
+ * 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.hadoop.ozone.om.helpers;
+
+import static java.util.Collections.emptyMap;
+import static java.util.Collections.singletonMap;
+import static org.assertj.core.api.Assertions.assertThat;
+
+import com.google.common.collect.ImmutableMap;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.LinkedHashMap;
+import java.util.Map;
+import java.util.function.Consumer;
+import java.util.stream.Stream;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.MethodSource;
+
+class TestMapBuilder {
+
+  @ParameterizedTest
+  @MethodSource("initialValues")
+  void testPut(ImmutableMap<String, String> initialValue) {
+    MapBuilder<String, String> subject = MapBuilder.of(initialValue);
+
+    if (!initialValue.isEmpty()) {
+      // unchanged by putting each initial entry
+      initialValue.forEach((k, v) -> assertBuildsInitialValue(subject, map -> 
map.put(k, v)));
+
+      // changed by putting existing keys with new value
+      for (Map.Entry<String, String> e : initialValue.entrySet()) {
+        assertChangedBy(subject, map -> map.put(e.getKey(), "newValue"));
+        assertThat(subject.build())
+            .containsEntry(e.getKey(), "newValue")
+            .hasSize(initialValue.size())
+            .containsOnlyKeys(initialValue.keySet());
+      }
+    }
+
+    assertChangedBy(subject, map -> map.put("newKey", "value"));
+
+    assertThat(subject.build())
+        .containsEntry("newKey", "value")
+        .hasSize(initialValue.size() + 1);
+  }
+
+  @Test
+  void testPutAll() {
+    MapBuilder<String, String> subject = MapBuilder.copyOf(singletonMap("key", 
"value"));
+
+    assertBuildsInitialValue(subject, map -> map.putAll(emptyMap()));
+
+    Map<String, String> newMap = ImmutableMap.of("newKey", "newValue", "key", 
"newValueForExistingKey");
+    assertChangedBy(subject, map -> map.putAll(newMap));
+    assertThat(subject.build())
+        .containsAllEntriesOf(newMap);
+  }
+
+  @ParameterizedTest
+  @MethodSource("initialValues")
+  void testRemove(ImmutableMap<String, String> initialValue) {
+    MapBuilder<String, String> subject = MapBuilder.of(initialValue);
+
+    assertBuildsInitialValue(subject, map -> map.remove("no-such-key"));
+
+    if (!initialValue.isEmpty()) {
+      Map<String, String> copy = new LinkedHashMap<>(initialValue);
+      for (Iterator<Map.Entry<String, String>> it = 
copy.entrySet().iterator(); it.hasNext();) {
+        Map.Entry<String, String> entry = it.next();
+        assertChangedBy(subject, map -> map.remove(entry.getKey()));
+        it.remove();
+        assertThat(subject.build())
+            .isNotSameAs(initialValue)
+            .containsExactlyEntriesOf(copy);
+      }
+    }
+  }
+
+  @ParameterizedTest
+  @MethodSource("initialValues")
+  void testSetSame(ImmutableMap<String, String> initialValue) {
+    MapBuilder<String, String> subject = MapBuilder.of(initialValue);
+
+    assertBuildsInitialValue(subject, map -> map.set(initialValue));
+  }
+
+  @Test
+  void testSetImmutable() {
+    MapBuilder<String, String> subject = MapBuilder.of(ImmutableMap.of("key", 
"value"));
+
+    ImmutableMap<String, String> newMap = ImmutableMap.of("newKey", 
"newValue");
+    assertChangedBy(subject, map -> map.set(newMap));
+
+    assertThat(subject.build())
+        .isSameAs(newMap);
+  }
+
+  @Test
+  void testSetMutable() {
+    MapBuilder<String, String> subject = MapBuilder.of(ImmutableMap.of("key", 
"value"));
+
+    Map<String, String> newMap = new HashMap<>(ImmutableMap.of("newKey", 
"newValue"));
+    assertChangedBy(subject, map -> map.set(newMap));
+
+    assertThat(subject.build())
+        .isEqualTo(newMap);
+  }
+
+  static Stream<ImmutableMap<String, String>> initialValues() {
+    return Stream.of(
+        ImmutableMap.of(),
+        ImmutableMap.of("k0", "v0"),
+        ImmutableMap.of("k1", "v1", "k2", "v2")
+    );
+  }
+
+  private static <K, V> void assertChangedBy(MapBuilder<K, V> subject, 
Consumer<MapBuilder<K, V>> op) {
+    final Map<K, V> before = subject.build();
+
+    op.accept(subject);
+    assertThat(subject.isChanged()).isTrue();
+    assertThat(subject.build()).isNotEqualTo(before);
+  }
+
+  private static <K, V> void assertUnchangedBy(MapBuilder<K, V> subject, 
Consumer<MapBuilder<K, V>> op) {
+    final boolean wasChanged = subject.isChanged();
+    final Map<K, V> before = subject.build();
+
+    op.accept(subject);
+
+    assertThat(subject.isChanged())
+        .isEqualTo(wasChanged);
+    assertThat(subject.build())
+        .isSameAs(before);
+  }
+
+  /** Same as {@link #assertUnchangedBy(MapBuilder, Consumer)}, but also 
verify that {@link MapBuilder#build()}
+   * returns the initial map instance. */
+  private static <K, V> void assertBuildsInitialValue(MapBuilder<K, V> 
subject, Consumer<MapBuilder<K, V>> op) {
+    assertUnchangedBy(subject, op);
+    assertThat(subject.build())
+        .isSameAs(subject.initialValue());
+  }
+}
diff --git 
a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmVolumeArgs.java
 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmVolumeArgs.java
index 869d153b429..fbed7b8cde5 100644
--- 
a/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmVolumeArgs.java
+++ 
b/hadoop-ozone/common/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmVolumeArgs.java
@@ -26,6 +26,7 @@
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
 import static org.junit.jupiter.api.Assertions.assertSame;
 
+import com.google.common.collect.ImmutableMap;
 import java.io.IOException;
 import java.util.Collections;
 import org.apache.hadoop.ozone.OzoneAcl;
@@ -98,8 +99,7 @@ private static OmVolumeArgs createSubject() {
         .setObjectID(1L)
         .setUpdateID(1L)
         .setQuotaInBytes(Long.MAX_VALUE)
-        .addMetadata("key1", "value1")
-        .addMetadata("key2", "value2")
+        .addAllMetadata(ImmutableMap.of("key1", "value1", "key2", "value2"))
         .addAcl(USER1_READ)
         .build();
   }
diff --git 
a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/helpers/OmPrefixInfo.java
 
b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/helpers/OmPrefixInfo.java
index 20a9fbdd4cf..e4eaae97202 100644
--- 
a/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/helpers/OmPrefixInfo.java
+++ 
b/hadoop-ozone/interface-storage/src/main/java/org/apache/hadoop/ozone/om/helpers/OmPrefixInfo.java
@@ -131,12 +131,6 @@ public Builder setName(String n) {
       return this;
     }
 
-    @Override
-    public OmPrefixInfo.Builder addMetadata(String key, String value) {
-      super.addMetadata(key, value);
-      return this;
-    }
-
     @Override
     public OmPrefixInfo.Builder addAllMetadata(
         Map<String, String> additionalMetadata) {
diff --git 
a/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfo.java
 
b/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfo.java
index 687136d16e9..cf23703fc71 100644
--- 
a/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfo.java
+++ 
b/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfo.java
@@ -17,6 +17,7 @@
 
 package org.apache.hadoop.ozone.om.helpers;
 
+import static java.util.Collections.singletonMap;
 import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotEquals;
@@ -147,8 +148,8 @@ public void testGetProtobuf() {
         IAccessAuthorizer.ACLIdentityType.USER,
         username, IAccessAuthorizer.ACLType.WRITE,
         ACCESS);
-    omPrefixInfo = new OmPrefixInfo.Builder(omPrefixInfo)
-        .addMetadata("key", "value")
+    omPrefixInfo = omPrefixInfo.toBuilder()
+        .addAllMetadata(singletonMap("key", "value"))
         .build();
     OzoneManagerStorageProtos.PersistedPrefixInfo pi =
         omPrefixInfo.getProtobuf();
diff --git 
a/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfoCodec.java
 
b/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfoCodec.java
index 75e5cdf7f41..6ece214236a 100644
--- 
a/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfoCodec.java
+++ 
b/hadoop-ozone/interface-storage/src/test/java/org/apache/hadoop/ozone/om/helpers/TestOmPrefixInfoCodec.java
@@ -17,6 +17,7 @@
 
 package org.apache.hadoop.ozone.om.helpers;
 
+import static java.util.Collections.singletonMap;
 import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS;
 import static org.junit.jupiter.api.Assertions.assertEquals;
 
@@ -49,7 +50,7 @@ public void testToAndFromPersistedFormat() throws IOException 
{
     OmPrefixInfo opiSave = OmPrefixInfo.newBuilder()
         .setName("/user/hive/warehouse")
         .setAcls(acls)
-        .addMetadata("id", "100")
+        .addAllMetadata(singletonMap("id", "100"))
         .build();
 
     final Codec<OmPrefixInfo> codec = getCodec();
diff --git 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java
 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java
index c1d73ea4b31..8db0b7402c9 100644
--- 
a/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java
+++ 
b/hadoop-ozone/ozone-manager/src/main/java/org/apache/hadoop/ozone/om/request/s3/multipart/S3MultipartUploadCompleteRequest.java
@@ -26,6 +26,7 @@
 import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.LinkedHashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.concurrent.atomic.AtomicReference;
@@ -521,7 +522,8 @@ protected OmKeyInfo getOmKeyInfo(long trxnLogIndex,
       final String multipartHash = multipartUploadedKeyHash(partKeyInfoMap);
       builder = omKeyInfo.toBuilder();
       if (dbOpenKeyInfo.getMetadata() != null) {
-        builder.setMetadata(dbOpenKeyInfo.getMetadata());
+        // make modifiable because ETAG needs to be added
+        builder.setMetadata(new LinkedHashMap<>(dbOpenKeyInfo.getMetadata()));
       }
       builder.addMetadata(OzoneConsts.ETAG, multipartHash);
       if (dbOpenKeyInfo.getTags() != null) {
diff --git 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/TestOMResponseUtils.java
 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/TestOMResponseUtils.java
index 274ada86105..a12d10e40e2 100644
--- 
a/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/TestOMResponseUtils.java
+++ 
b/hadoop-ozone/ozone-manager/src/test/java/org/apache/hadoop/ozone/om/response/TestOMResponseUtils.java
@@ -17,6 +17,8 @@
 
 package org.apache.hadoop.ozone.om.response;
 
+import static java.util.Collections.singletonMap;
+
 import org.apache.hadoop.ozone.om.helpers.OmBucketInfo;
 import org.apache.hadoop.util.Time;
 
@@ -29,10 +31,14 @@ public final class TestOMResponseUtils {
   private TestOMResponseUtils() {
   }
 
-  public static  OmBucketInfo createBucket(String volume, String bucket) {
-    return 
OmBucketInfo.newBuilder().setVolumeName(volume).setBucketName(bucket)
-        .setCreationTime(Time.now()).setIsVersionEnabled(true).addMetadata(
-            "key1", "value1").build();
+  public static OmBucketInfo createBucket(String volume, String bucket) {
+    return OmBucketInfo.newBuilder()
+        .setVolumeName(volume)
+        .setBucketName(bucket)
+        .setCreationTime(Time.now())
+        .setIsVersionEnabled(true)
+        .addAllMetadata(singletonMap("key1", "value1"))
+        .build();
 
   }
 
diff --git 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/NSSummaryTests.java
 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/NSSummaryTests.java
index 52d43d38e08..9f5ff85edfc 100644
--- 
a/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/NSSummaryTests.java
+++ 
b/hadoop-ozone/recon/src/test/java/org/apache/hadoop/ozone/recon/api/NSSummaryTests.java
@@ -18,6 +18,7 @@
 package org.apache.hadoop.ozone.recon.api;
 
 import static java.util.Collections.singletonList;
+import static java.util.Collections.singletonMap;
 import static org.apache.hadoop.ozone.OzoneAcl.AclScope.ACCESS;
 import static 
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLIdentityType.USER;
 import static 
org.apache.hadoop.ozone.security.acl.IAccessAuthorizer.ACLType.WRITE;
@@ -60,7 +61,7 @@ public static void testNSSummaryBasicInfoRoot(
         .setObjectID(10)
         .setUpdateID(100)
         .setAcls(singletonList(OzoneAcl.of(USER, username, ACCESS, WRITE)))
-        .addMetadata("key", "value")
+        .addAllMetadata(singletonMap("key", "value"))
         .build();
     reconOMMetadataManager.getPrefixTable()
         .put(OzoneConsts.OM_KEY_PREFIX, omPrefixInfo);


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

Reply via email to