|
26 | 26 | import java.util.ArrayList; |
27 | 27 | import java.util.List; |
28 | 28 | import java.util.Random; |
| 29 | +import java.util.concurrent.Callable; |
29 | 30 | import java.util.concurrent.CountDownLatch; |
30 | 31 | import java.util.concurrent.CyclicBarrier; |
| 32 | +import java.util.concurrent.ExecutionException; |
31 | 33 | import java.util.concurrent.ExecutorService; |
| 34 | +import java.util.concurrent.Executors; |
| 35 | +import java.util.concurrent.Future; |
32 | 36 | import java.util.concurrent.RejectedExecutionException; |
33 | 37 | import java.util.concurrent.ScheduledThreadPoolExecutor; |
34 | 38 | import java.util.concurrent.ThreadPoolExecutor; |
@@ -178,7 +182,7 @@ void testAdjustThreadPoolSizeBasedOnLowCPU() |
178 | 182 | try (AzureBlobFileSystem abfs = (AzureBlobFileSystem) fileSystem) { |
179 | 183 | WriteThreadPoolSizeManager instance |
180 | 184 | = WriteThreadPoolSizeManager.getInstance(abfs.getFileSystemId(), |
181 | | - getAbfsStore(abfs).getAbfsConfiguration(), |
| 185 | + mockConfig, |
182 | 186 | abfs.getAbfsClient().getAbfsCounters()); |
183 | 187 | ExecutorService executor = instance.getExecutorService(); |
184 | 188 | int initialSize = ((ThreadPoolExecutor) executor).getMaximumPoolSize(); |
@@ -833,8 +837,11 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate() |
833 | 837 | .getAbfsWriteResourceUtilizationMetrics(); |
834 | 838 |
|
835 | 839 | 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()); |
838 | 845 |
|
839 | 846 | ThreadPoolExecutor executor = |
840 | 847 | (ThreadPoolExecutor) instance.getExecutorService(); |
@@ -869,8 +876,11 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate() |
869 | 876 | Thread.sleep(SLEEP_DURATION_30S_MS); |
870 | 877 |
|
871 | 878 | 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()); |
874 | 884 |
|
875 | 885 | //--- Validate that metrics and stats changed --- |
876 | 886 | Assertions.assertThat(statsAfter) |
@@ -900,5 +910,54 @@ void testThreadPoolOnLowCpuLoadAndMetricsUpdate() |
900 | 910 | instance.close(); |
901 | 911 | } |
902 | 912 | } |
| 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 | + } |
903 | 962 | } |
904 | 963 |
|
0 commit comments