From a66db0f63640f234135c9b4ee92d15fe32d659e9 Mon Sep 17 00:00:00 2001 From: nir Date: Sun, 19 Jan 2025 16:03:24 +0200 Subject: [PATCH] HADOOP-19387: Fix LocalDirAllocator::getLocalPathForWrite unable to recover when the thread is interrupted --- .../apache/hadoop/fs/LocalDirAllocator.java | 2 +- .../hadoop/fs/TestLocalDirAllocator.java | 18 ++++++++++++++++++ 2 files changed, 19 insertions(+), 1 deletion(-) diff --git a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java index d8ab16f41d3ac..b8c26c677f4e3 100644 --- a/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java +++ b/hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java @@ -346,9 +346,9 @@ private Context confChanged(Configuration conf) } ctx.localDirs = dirs.toArray(new Path[dirs.size()]); ctx.dirDF = dfList.toArray(new DF[dirs.size()]); - ctx.savedLocalDirs = newLocalDirs; if (dirs.size() > 0) { + ctx.savedLocalDirs = newLocalDirs; // randomize the first disk picked in the round-robin selection ctx.dirNumLastAccessed.set(dirIndexRandomizer.nextInt(dirs.size())); } diff --git a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalDirAllocator.java b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalDirAllocator.java index 3693b4f0acde3..73d4616d29474 100644 --- a/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalDirAllocator.java +++ b/hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalDirAllocator.java @@ -567,5 +567,23 @@ public void testDirectoryRecovery() throws Throwable { // and expect to get a new file back dirAllocator.getLocalPathForWrite("file2", -1, conf); } + + /** + * Test for HADOOP-19387 LocalDirAllocator cannot recover after thread interruption. + */ + @Test(timeout = 30000) + public void testInterruptionRecovery() throws Throwable { + + String dir0 = buildBufferDir(ROOT, 7); + conf.set(CONTEXT, dir0); + try { + Thread.currentThread().interrupt(); + assertThrows(DiskErrorException.class, () -> dirAllocator.getLocalPathForWrite("file2", 1, conf)); + } finally { + Thread.interrupted(); + } + // expect to get a file with no exceptions + dirAllocator.getLocalPathForWrite("file2", 1, conf); + } }