Skip to content

Commit c10f16f

Browse files
PR comments
1 parent d9c1ab3 commit c10f16f

4 files changed

Lines changed: 91 additions & 22 deletions

File tree

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/JvmIdProvider.java

Lines changed: 27 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,37 +21,50 @@
2121
import java.util.Random;
2222

2323
/**
24-
* Provides a JVM-scoped unique identifier.
24+
* Provides a JVM-scoped identifier.
2525
*
2626
* <p>The identifier is generated once when the class is loaded and remains
27-
* constant for the lifetime of the JVM. The value is a random 6-digit number
28-
* in the range {@code [100000, 999999]}.</p>
27+
* constant for the lifetime of the JVM. It is derived using a combination of
28+
* the current system time and random entropy to reduce the likelihood of
29+
* collisions across JVM instances.</p>
30+
*
31+
* <p>The identifier is intended for lightweight JVM-level identification,
32+
* such as tagging metrics or log entries. It provides best-effort uniqueness
33+
* and is not guaranteed to be globally unique.</p>
2934
*
3035
* <p>This class is utility-only and cannot be instantiated.</p>
3136
*/
3237
public final class JvmIdProvider {
3338

34-
/**
35-
* A JVM-wide unique identifier generated at class load time.
36-
*/
37-
private static final long JVM_UNIQUE_ID;
39+
/** Lower bound (inclusive) for the generated JVM identifier. */
40+
private static final int MIN_JVM_ID = 100_000;
41+
42+
/** Size of the identifier value range. */
43+
private static final int JVM_ID_RANGE = 900_000;
44+
45+
/** Upper bound for random entropy mixed into the identifier. */
46+
private static final int RANDOM_ENTROPY_BOUND = 1_000;
47+
48+
/** JVM-scoped identifier generated at class initialization time. */
49+
private static final int JVM_UNIQUE_ID;
3850

3951
static {
40-
JVM_UNIQUE_ID = 100000L + new Random().nextInt(900000);
52+
long time = System.currentTimeMillis();
53+
int random = new Random().nextInt(RANDOM_ENTROPY_BOUND);
54+
JVM_UNIQUE_ID = (int) ((time + random) % JVM_ID_RANGE) + MIN_JVM_ID;
4155
}
4256

43-
/**
44-
* Prevents instantiation.
45-
*/
57+
/** Prevents instantiation. */
4658
private JvmIdProvider() {
4759
}
4860

4961
/**
50-
* Returns the JVM-scoped unique identifier.
62+
* Returns the JVM-scoped identifier.
5163
*
52-
* @return the unique ID for this JVM instance
64+
* @return an identifier that remains constant for the lifetime of the JVM
5365
*/
54-
public static long getJvmId() {
66+
public static int getJvmId() {
5567
return JVM_UNIQUE_ID;
5668
}
5769
}
70+

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/AbstractAbfsResourceUtilizationMetrics.java

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,8 +19,6 @@
1919
package org.apache.hadoop.fs.azurebfs.services;
2020

2121
import java.util.Arrays;
22-
import java.util.concurrent.atomic.AtomicBoolean;
23-
import java.util.concurrent.atomic.AtomicLong;
2422
import java.util.stream.Stream;
2523

2624
import org.slf4j.Logger;

hadoop-tools/hadoop-azure/src/main/java/org/apache/hadoop/fs/azurebfs/services/ReadBufferManagerV2.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@
5252
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.SCALE_DIRECTION_NO_UP_AT_MAX;
5353
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.SCALE_DIRECTION_UP;
5454
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.ZERO;
55-
import static org.apache.hadoop.fs.azurebfs.constants.FileSystemConfigurations.ZERO_D;
5655

5756
/**
5857
* The Improved Read Buffer Manager for Rest AbfsClient.

hadoop-tools/hadoop-azure/src/test/java/org/apache/hadoop/fs/azurebfs/TestWriteThreadPoolSizeManager.java

Lines changed: 64 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -26,9 +26,13 @@
2626
import java.util.ArrayList;
2727
import java.util.List;
2828
import java.util.Random;
29+
import java.util.concurrent.Callable;
2930
import java.util.concurrent.CountDownLatch;
3031
import java.util.concurrent.CyclicBarrier;
32+
import java.util.concurrent.ExecutionException;
3133
import java.util.concurrent.ExecutorService;
34+
import java.util.concurrent.Executors;
35+
import java.util.concurrent.Future;
3236
import java.util.concurrent.RejectedExecutionException;
3337
import java.util.concurrent.ScheduledThreadPoolExecutor;
3438
import java.util.concurrent.ThreadPoolExecutor;
@@ -178,7 +182,7 @@ void testAdjustThreadPoolSizeBasedOnLowCPU()
178182
try (AzureBlobFileSystem abfs = (AzureBlobFileSystem) fileSystem) {
179183
WriteThreadPoolSizeManager instance
180184
= WriteThreadPoolSizeManager.getInstance(abfs.getFileSystemId(),
181-
getAbfsStore(abfs).getAbfsConfiguration(),
185+
mockConfig,
182186
abfs.getAbfsClient().getAbfsCounters());
183187
ExecutorService executor = instance.getExecutorService();
184188
int initialSize = ((ThreadPoolExecutor) executor).getMaximumPoolSize();
@@ -833,8 +837,11 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate()
833837
.getAbfsWriteResourceUtilizationMetrics();
834838

835839
WriteThreadPoolSizeManager.WriteThreadPoolStats statsBefore =
836-
instance.getCurrentStats(ResourceUtilizationUtils.getJvmCpuLoad(), ResourceUtilizationUtils.getMemoryLoad(), ResourceUtilizationUtils.getUsedHeapMemory(),
837-
ResourceUtilizationUtils.getAvailableHeapMemory(), ResourceUtilizationUtils.getCommittedHeapMemory());
840+
instance.getCurrentStats(ResourceUtilizationUtils.getJvmCpuLoad(),
841+
ResourceUtilizationUtils.getMemoryLoad(),
842+
ResourceUtilizationUtils.getUsedHeapMemory(),
843+
ResourceUtilizationUtils.getAvailableHeapMemory(),
844+
ResourceUtilizationUtils.getCommittedHeapMemory());
838845

839846
ThreadPoolExecutor executor =
840847
(ThreadPoolExecutor) instance.getExecutorService();
@@ -869,8 +876,11 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate()
869876
Thread.sleep(SLEEP_DURATION_30S_MS);
870877

871878
WriteThreadPoolSizeManager.WriteThreadPoolStats statsAfter =
872-
instance.getCurrentStats(ResourceUtilizationUtils.getJvmCpuLoad(), ResourceUtilizationUtils.getMemoryLoad(), ResourceUtilizationUtils.getUsedHeapMemory(),
873-
ResourceUtilizationUtils.getAvailableHeapMemory(), ResourceUtilizationUtils.getCommittedHeapMemory());
879+
instance.getCurrentStats(ResourceUtilizationUtils.getJvmCpuLoad(),
880+
ResourceUtilizationUtils.getMemoryLoad(),
881+
ResourceUtilizationUtils.getUsedHeapMemory(),
882+
ResourceUtilizationUtils.getAvailableHeapMemory(),
883+
ResourceUtilizationUtils.getCommittedHeapMemory());
874884

875885
//--- Validate that metrics and stats changed ---
876886
Assertions.assertThat(statsAfter)
@@ -900,5 +910,54 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate()
900910
instance.close();
901911
}
902912
}
913+
914+
/**
915+
* Verifies that the JVM identifier is initialized once and remains
916+
* constant across multiple invocations within the same JVM process.
917+
*/
918+
@Test
919+
public void testJvmIdIsSingletonWithinJvm() {
920+
int firstId = JvmIdProvider.getJvmId();
921+
int secondId = JvmIdProvider.getJvmId();
922+
int thirdId = JvmIdProvider.getJvmId();
923+
924+
assertEquals(firstId, secondId,
925+
"Subsequent calls to getJvmId() should return the same value");
926+
assertEquals(secondId, thirdId,
927+
"JVM-scoped identifier must remain constant for the lifetime of the JVM");
928+
}
929+
930+
/**
931+
* Verifies that the JVM identifier is safely shared across multiple threads
932+
* and that concurrent access returns the same value.
933+
*
934+
* <p>This test ensures that static initialization of the identifier is
935+
* thread-safe and occurs only once per JVM.</p>
936+
*/
937+
@Test
938+
public void testJvmIdIsSameAcrossThreads()
939+
throws ExecutionException, InterruptedException {
940+
941+
ExecutorService executor = Executors.newFixedThreadPool(4);
942+
943+
try {
944+
Callable<Integer> task = JvmIdProvider::getJvmId;
945+
Future<Integer> f1 = executor.submit(task);
946+
Future<Integer> f2 = executor.submit(task);
947+
Future<Integer> f3 = executor.submit(task);
948+
Future<Integer> f4 = executor.submit(task);
949+
950+
int expectedId = f1.get();
951+
assertEquals(expectedId, f2.get(),
952+
"JVM ID should be identical when accessed from different threads");
953+
assertEquals(expectedId, f3.get(),
954+
"JVM ID should be identical when accessed concurrently");
955+
assertEquals(expectedId, f4.get(),
956+
"JVM ID should be initialized once and shared across all threads");
957+
} finally {
958+
executor.shutdown();
959+
executor.awaitTermination(5, TimeUnit.SECONDS);
960+
}
961+
}
903962
}
904963

0 commit comments

Comments
 (0)