Skip to content

Commit c66d59d

Browse files
hotcodemachaHarshitGupta11
authored andcommitted
HADOOP-16769. LocalDirAllocator to provide diagnostics when file creation fails (apache#4842)
The patch provides detailed diagnostics of file creation failure in LocalDirAllocator. Contributed by: Ashutosh Gupta
1 parent c00588b commit c66d59d

File tree

2 files changed

+39
-4
lines changed

2 files changed

+39
-4
lines changed

hadoop-common-project/hadoop-common/src/main/java/org/apache/hadoop/fs/LocalDirAllocator.java

Lines changed: 22 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -396,6 +396,10 @@ public Path getLocalPathForWrite(String pathStr, long size,
396396
Context ctx = confChanged(conf);
397397
int numDirs = ctx.localDirs.length;
398398
int numDirsSearched = 0;
399+
// Max capacity in any directory
400+
long maxCapacity = 0;
401+
String errorText = null;
402+
IOException diskException = null;
399403
//remove the leading slash from the path (to make sure that the uri
400404
//resolution results in a valid path on the dir being checked)
401405
if (pathStr.startsWith("/")) {
@@ -444,9 +448,18 @@ public Path getLocalPathForWrite(String pathStr, long size,
444448
int dirNum = ctx.getAndIncrDirNumLastAccessed(randomInc);
445449
while (numDirsSearched < numDirs) {
446450
long capacity = ctx.dirDF[dirNum].getAvailable();
451+
if (capacity > maxCapacity) {
452+
maxCapacity = capacity;
453+
}
447454
if (capacity > size) {
448-
returnPath =
449-
createPath(ctx.localDirs[dirNum], pathStr, checkWrite);
455+
try {
456+
returnPath = createPath(ctx.localDirs[dirNum], pathStr,
457+
checkWrite);
458+
} catch (IOException e) {
459+
errorText = e.getMessage();
460+
diskException = e;
461+
LOG.debug("DiskException caught for dir {}", ctx.localDirs[dirNum], e);
462+
}
450463
if (returnPath != null) {
451464
ctx.getAndIncrDirNumLastAccessed(numDirsSearched);
452465
break;
@@ -462,8 +475,13 @@ public Path getLocalPathForWrite(String pathStr, long size,
462475
}
463476

464477
//no path found
465-
throw new DiskErrorException("Could not find any valid local " +
466-
"directory for " + pathStr);
478+
String newErrorText = "Could not find any valid local directory for " +
479+
pathStr + " with requested size " + size +
480+
" as the max capacity in any directory is " + maxCapacity;
481+
if (errorText != null) {
482+
newErrorText = newErrorText + " due to " + errorText;
483+
}
484+
throw new DiskErrorException(newErrorText, diskException);
467485
}
468486

469487
/** Creates a file on the local FS. Pass size as

hadoop-common-project/hadoop-common/src/test/java/org/apache/hadoop/fs/TestLocalDirAllocator.java

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
import java.util.NoSuchElementException;
2727

2828
import org.apache.hadoop.conf.Configuration;
29+
import org.apache.hadoop.test.LambdaTestUtils;
2930
import org.apache.hadoop.util.DiskChecker.DiskErrorException;
3031
import org.apache.hadoop.util.Shell;
3132

@@ -532,4 +533,20 @@ public void testGetLocalPathForWriteForInvalidPaths() throws Exception {
532533
}
533534
}
534535

536+
/**
537+
* Test to verify LocalDirAllocator log details to provide diagnostics when file creation fails.
538+
*
539+
* @throws Exception
540+
*/
541+
@Test(timeout = 30000)
542+
public void testGetLocalPathForWriteForLessSpace() throws Exception {
543+
String dir0 = buildBufferDir(ROOT, 0);
544+
String dir1 = buildBufferDir(ROOT, 1);
545+
conf.set(CONTEXT, dir0 + "," + dir1);
546+
LambdaTestUtils.intercept(DiskErrorException.class,
547+
String.format("Could not find any valid local directory for %s with requested size %s",
548+
"p1/x", Long.MAX_VALUE - 1), "Expect a DiskErrorException.",
549+
() -> dirAllocator.getLocalPathForWrite("p1/x", Long.MAX_VALUE - 1, conf));
550+
}
535551
}
552+

0 commit comments

Comments
 (0)