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 72fa9652aa3 HDDS-15602. Read pipeline ID does not need to use secure 
random (#10571)
72fa9652aa3 is described below

commit 72fa9652aa3c2be40a585fbc3054fbdde397642e
Author: Ivan Andika <[email protected]>
AuthorDate: Tue Jun 23 18:56:15 2026 +0800

    HDDS-15602. Read pipeline ID does not need to use secure random (#10571)
---
 .../hadoop/hdds/scm/pipeline/PipelineID.java       | 15 ++++++++++++
 .../org/apache/hadoop/ozone/util/UUIDUtil.java     | 13 ++++++++++-
 .../hdds/scm/container/ContainerReplica.java       |  9 ++++++++
 .../hdds/scm/pipeline/ECPipelineProvider.java      | 21 ++++++++---------
 .../hadoop/hdds/scm/pipeline/PipelineProvider.java |  7 ++++++
 .../hdds/scm/pipeline/RatisPipelineProvider.java   | 23 +++++++-----------
 .../hdds/scm/pipeline/SimplePipelineProvider.java  | 27 +++++++++++-----------
 7 files changed, 73 insertions(+), 42 deletions(-)

diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineID.java
 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineID.java
index d7ea21d024e..bb2aa7cc626 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineID.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineID.java
@@ -18,12 +18,14 @@
 package org.apache.hadoop.hdds.scm.pipeline;
 
 import com.fasterxml.jackson.annotation.JsonIgnore;
+import java.nio.ByteBuffer;
 import java.util.UUID;
 import java.util.function.Supplier;
 import org.apache.hadoop.hdds.protocol.proto.HddsProtos;
 import org.apache.hadoop.hdds.utils.db.Codec;
 import org.apache.hadoop.hdds.utils.db.DelegatedCodec;
 import org.apache.hadoop.hdds.utils.db.UuidCodec;
+import org.apache.hadoop.ozone.util.UUIDUtil;
 import org.apache.ratis.util.MemoizedSupplier;
 
 /**
@@ -52,6 +54,19 @@ public static PipelineID randomId() {
     return new PipelineID(UUID.randomUUID());
   }
 
+  /**
+   * Generates a random PipelineID using {@link java.util.Random} instead of
+   * {@link java.security.SecureRandom}. This avoids contention on the shared
+   * {@code SecureRandom} instance and is suitable for non-sensitive,
+   * throwaway IDs such as read pipelines, where predictability of the next
+   * ID has no security impact.
+   */
+  public static PipelineID insecureRandomId() {
+    byte[] bytes = UUIDUtil.insecureRandomUUIDBytes();
+    ByteBuffer buf = ByteBuffer.wrap(bytes);
+    return new PipelineID(new UUID(buf.getLong(), buf.getLong()));
+  }
+
   public static PipelineID valueOf(UUID id) {
     return new PipelineID(id);
   }
diff --git 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/util/UUIDUtil.java 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/util/UUIDUtil.java
index 6644b8a4a25..8f4da0cfc46 100644
--- 
a/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/util/UUIDUtil.java
+++ 
b/hadoop-hdds/common/src/main/java/org/apache/hadoop/ozone/util/UUIDUtil.java
@@ -18,16 +18,27 @@
 package org.apache.hadoop.ozone.util;
 
 import java.security.SecureRandom;
+import java.util.Random;
+import java.util.function.Consumer;
 
 /**
  * Helper methods to deal with random UUIDs.
  */
 public final class UUIDUtil {
   private static final ThreadLocal<SecureRandom> GENERATOR = 
ThreadLocal.withInitial(SecureRandom::new);
+  private static final ThreadLocal<Random> INSECURE_GENERATOR = 
ThreadLocal.withInitial(Random::new);
 
   public static byte[] randomUUIDBytes() {
+    return getUUIDBytes(GENERATOR.get()::nextBytes);
+  }
+
+  public static byte[] insecureRandomUUIDBytes() {
+    return getUUIDBytes(INSECURE_GENERATOR.get()::nextBytes);
+  }
+
+  private static byte[] getUUIDBytes(Consumer<byte[]> generator) {
     final byte[] bytes = new byte[16];
-    GENERATOR.get().nextBytes(bytes);
+    generator.accept(bytes);
     // See RFC 4122 section 4.4
     bytes[6]  &= 0x0f;
     bytes[6]  |= 0x40;
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplica.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplica.java
index 5c9bd57cd88..d26cc4a3563 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplica.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/container/ContainerReplica.java
@@ -17,7 +17,10 @@
 
 package org.apache.hadoop.hdds.scm.container;
 
+import java.util.List;
 import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
 import org.apache.commons.lang3.builder.CompareToBuilder;
 import org.apache.commons.lang3.builder.EqualsBuilder;
 import org.apache.commons.lang3.builder.HashCodeBuilder;
@@ -165,6 +168,12 @@ public int compareTo(ContainerReplica that) {
         .build();
   }
 
+  public static List<DatanodeDetails> 
toDatanodeDetailsList(Set<ContainerReplica> replicas) {
+    return replicas.stream()
+        .map(ContainerReplica::getDatanodeDetails)
+        .collect(Collectors.toList());
+  }
+
   /**
    * Returns a new Builder to construct ContainerReplica.
    *
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/ECPipelineProvider.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/ECPipelineProvider.java
index f9b94bd8d0d..1560c9890c5 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/ECPipelineProvider.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/ECPipelineProvider.java
@@ -103,7 +103,10 @@ protected Pipeline create(ECReplicationConfig 
replicationConfig,
       ecIndex++;
     }
 
-    return createPipelineInternal(replicationConfig, nodes, dnIndexes);
+    return newPipelineBuilder(replicationConfig, nodes)
+        .setId(PipelineID.randomId())
+        .setReplicaIndexes(dnIndexes)
+        .build();
   }
 
   @Override
@@ -130,17 +133,11 @@ public Pipeline createForRead(
 
     dns.sort(Comparator.comparing(nodeStatusMap::get, 
CREATE_FOR_READ_COMPARATOR));
 
-    return createPipelineInternal(replicationConfig, dns, map);
-  }
-
-  private Pipeline createPipelineInternal(ECReplicationConfig repConfig,
-      List<DatanodeDetails> dns, Map<DatanodeDetails, Integer> indexes) {
-    return Pipeline.newBuilder()
-        .setId(PipelineID.randomId())
-        .setState(Pipeline.PipelineState.ALLOCATED)
-        .setReplicationConfig(repConfig)
-        .setNodes(dns)
-        .setReplicaIndexes(indexes)
+    // Use insecureRandomId for throwaway read pipeline IDs to avoid
+    // contention on the shared SecureRandom instance.
+    return newPipelineBuilder(replicationConfig, dns)
+        .setId(PipelineID.insecureRandomId())
+        .setReplicaIndexes(map)
         .build();
   }
 
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineProvider.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineProvider.java
index b1b2d734906..0b8506f58c2 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineProvider.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/PipelineProvider.java
@@ -139,4 +139,11 @@ List<DatanodeDetails> pickAllNodesNotUsed(
     }
     return dns;
   }
+
+  protected Pipeline.Builder newPipelineBuilder(ReplicationConfig 
replicationConfig, List<DatanodeDetails> nodes) {
+    return Pipeline.newBuilder()
+        .setNodes(nodes)
+        .setReplicationConfig(replicationConfig)
+        .setState(Pipeline.PipelineState.ALLOCATED);
+  }
 }
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/RatisPipelineProvider.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/RatisPipelineProvider.java
index 8fe6934f1ed..30eb83ab735 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/RatisPipelineProvider.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/RatisPipelineProvider.java
@@ -23,7 +23,6 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
-import java.util.stream.Collectors;
 import org.apache.hadoop.hdds.client.RatisReplicationConfig;
 import org.apache.hadoop.hdds.conf.ConfigurationSource;
 import org.apache.hadoop.hdds.conf.StorageUnit;
@@ -182,13 +181,9 @@ public synchronized Pipeline create(RatisReplicationConfig 
replicationConfig,
 
     DatanodeDetails suggestedLeader = leaderChoosePolicy.chooseLeader(dns);
 
-    Pipeline pipeline = Pipeline.newBuilder()
+    Pipeline pipeline = 
newPipelineBuilder(RatisReplicationConfig.getInstance(factor), dns)
         .setId(PipelineID.randomId())
-        .setState(PipelineState.ALLOCATED)
-        .setReplicationConfig(RatisReplicationConfig.getInstance(factor))
-        .setNodes(dns)
-        .setSuggestedLeaderId(
-            suggestedLeader != null ? suggestedLeader.getID() : null)
+        .setSuggestedLeaderId(suggestedLeader != null ? 
suggestedLeader.getID() : null)
         .build();
 
     // Send command to datanodes to create pipeline
@@ -213,11 +208,8 @@ public synchronized Pipeline create(RatisReplicationConfig 
replicationConfig,
   @Override
   public Pipeline create(RatisReplicationConfig replicationConfig,
       List<DatanodeDetails> nodes) {
-    return Pipeline.newBuilder()
+    return newPipelineBuilder(replicationConfig, nodes)
         .setId(PipelineID.randomId())
-        .setState(PipelineState.ALLOCATED)
-        .setReplicationConfig(replicationConfig)
-        .setNodes(nodes)
         .build();
   }
 
@@ -225,10 +217,11 @@ public Pipeline create(RatisReplicationConfig 
replicationConfig,
   public Pipeline createForRead(
       RatisReplicationConfig replicationConfig,
       Set<ContainerReplica> replicas) {
-    return create(replicationConfig, replicas
-        .stream()
-        .map(ContainerReplica::getDatanodeDetails)
-        .collect(Collectors.toList()));
+    // Use insecureRandomId for throwaway read pipeline IDs to avoid
+    // contention on the shared SecureRandom instance.
+    return newPipelineBuilder(replicationConfig, 
ContainerReplica.toDatanodeDetailsList(replicas))
+        .setId(PipelineID.insecureRandomId())
+        .build();
   }
 
   private List<DatanodeDetails> filterPipelineEngagement() {
diff --git 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/SimplePipelineProvider.java
 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/SimplePipelineProvider.java
index a7cfd4bd597..50ed2b015b9 100644
--- 
a/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/SimplePipelineProvider.java
+++ 
b/hadoop-hdds/server-scm/src/main/java/org/apache/hadoop/hdds/scm/pipeline/SimplePipelineProvider.java
@@ -21,7 +21,7 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
-import java.util.stream.Collectors;
+import org.apache.hadoop.hdds.client.ReplicationConfig;
 import org.apache.hadoop.hdds.client.StandaloneReplicationConfig;
 import org.apache.hadoop.hdds.protocol.DatanodeDetails;
 import org.apache.hadoop.hdds.scm.container.ContainerReplica;
@@ -61,33 +61,27 @@ public Pipeline create(StandaloneReplicationConfig 
replicationConfig,
     }
 
     Collections.shuffle(dns);
-    return Pipeline.newBuilder()
+    return newPipelineBuilder(replicationConfig, dns.subList(0, 
replicationConfig.getReplicationFactor().getNumber()))
         .setId(PipelineID.randomId())
-        .setState(PipelineState.OPEN)
-        .setReplicationConfig(replicationConfig)
-        .setNodes(dns.subList(0,
-            replicationConfig.getReplicationFactor().getNumber()))
         .build();
   }
 
   @Override
   public Pipeline create(StandaloneReplicationConfig replicationConfig,
       List<DatanodeDetails> nodes) {
-    return Pipeline.newBuilder()
+    return newPipelineBuilder(replicationConfig, nodes)
         .setId(PipelineID.randomId())
-        .setState(PipelineState.OPEN)
-        .setReplicationConfig(replicationConfig)
-        .setNodes(nodes)
         .build();
   }
 
   @Override
   public Pipeline createForRead(StandaloneReplicationConfig replicationConfig,
       Set<ContainerReplica> replicas) {
-    return create(replicationConfig, replicas
-        .stream()
-        .map(ContainerReplica::getDatanodeDetails)
-        .collect(Collectors.toList()));
+    // Use insecureRandomId for throwaway read pipeline IDs to avoid
+    // contention on the shared SecureRandom instance.
+    return newPipelineBuilder(replicationConfig, 
ContainerReplica.toDatanodeDetailsList(replicas))
+        .setId(PipelineID.insecureRandomId())
+        .build();
   }
 
   @Override
@@ -95,4 +89,9 @@ public void close(Pipeline pipeline) throws IOException {
 
   }
 
+  @Override
+  protected Pipeline.Builder newPipelineBuilder(ReplicationConfig 
replicationConfig, List<DatanodeDetails> nodes) {
+    return super.newPipelineBuilder(replicationConfig, nodes)
+        .setState(PipelineState.OPEN);
+  }
 }


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

Reply via email to