Skip to content

Commit 0413eb3

Browse files
committed
HDFS-17049. EC: Fix duplicate block group IDs generated by SequentialBlockGroupIdGenerator.
1 parent f0c4286 commit 0413eb3

File tree

2 files changed

+40
-1
lines changed

2 files changed

+40
-1
lines changed

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/blockmanagement/SequentialBlockGroupIdGenerator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ public class SequentialBlockGroupIdGenerator extends SequentialNumber {
5151
}
5252

5353
@Override // NumberGenerator
54-
public long nextValue() {
54+
synchronized public long nextValue() {
5555
skipTo((getCurrentValue() & ~BLOCK_GROUP_INDEX_MASK) + MAX_BLOCKS_IN_GROUP);
5656
// Make sure there's no conflict with existing random block IDs
5757
final Block b = new Block(getCurrentValue());

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/server/blockmanagement/TestSequentialBlockGroupId.java

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,11 +22,15 @@
2222
import static org.hamcrest.CoreMatchers.is;
2323
import static org.hamcrest.CoreMatchers.not;
2424
import static org.junit.Assert.assertThat;
25+
import static org.junit.Assert.fail;
2526
import static org.mockito.Mockito.doAnswer;
2627
import static org.mockito.Mockito.spy;
2728

2829
import java.io.IOException;
30+
import java.util.ArrayList;
31+
import java.util.HashSet;
2932
import java.util.List;
33+
import java.util.Set;
3034

3135
import org.slf4j.Logger;
3236
import org.slf4j.LoggerFactory;
@@ -172,6 +176,41 @@ public void testTriggerBlockGroupIdCollision() throws IOException {
172176
}
173177
}
174178

179+
/**
180+
* Test that the values generated by blockGroup ID generator are unique,
181+
* even if they are generated concurrently.
182+
* @throws Exception
183+
*/
184+
@Test
185+
public void testBlockGroupIdThreadSafety() throws Exception {
186+
List<List<Long>> blockIds = new ArrayList<>();
187+
List<Thread> threads = new ArrayList<>();
188+
for (int i = 0; i < 20; i++) {
189+
blockIds.add(new ArrayList<>());
190+
threads.add(new Thread(() -> {
191+
for (int j = 0; j < 1000; j++) {
192+
long next = blockGrpIdGenerator.nextValue();
193+
blockIds.get(j).add(next);
194+
}
195+
}));
196+
}
197+
for (Thread t : threads) {
198+
t.start();
199+
}
200+
for (Thread t : threads) {
201+
t.join();
202+
}
203+
Set<Long> allBlockIds = new HashSet<>();
204+
for (List<Long> set : blockIds) {
205+
for (long id : set) {
206+
if (allBlockIds.contains(id)) {
207+
fail("Same block group id is generated!");
208+
}
209+
allBlockIds.add(id);
210+
}
211+
}
212+
}
213+
175214
/**
176215
* Test that collisions in the blockGroup ID when the id is occupied by legacy
177216
* block.

0 commit comments

Comments
 (0)