From 97bffaa0e52d38828ee977d8bb4d9f065e72010e Mon Sep 17 00:00:00 2001 From: lgh Date: Tue, 30 Apr 2024 10:23:42 +0800 Subject: [PATCH 1/9] HDFS-17509 RBF: Fix ClientProtocol.concat will throw NPE if tgr is a empty file. --- .../router/RouterClientProtocol.java | 51 +++++++++---------- .../federation/router/RouterRpcServer.java | 36 ------------- .../federation/router/TestRouterRpc.java | 11 ++++ 3 files changed, 34 insertions(+), 64 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index 7350583264b2c..075ad346b7dfa 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -667,39 +667,34 @@ public void rename2(final String src, final String dst, public void concat(String trg, String[] src) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.WRITE); - // See if the src and target files are all in the same namespace - LocatedBlocks targetBlocks = getBlockLocations(trg, 0, 1); - if (targetBlocks == null) { - throw new IOException("Cannot locate blocks for target file - " + trg); - } - LocatedBlock lastLocatedBlock = targetBlocks.getLastLocatedBlock(); - String targetBlockPoolId = lastLocatedBlock.getBlock().getBlockPoolId(); - for (String source : src) { - LocatedBlocks sourceBlocks = getBlockLocations(source, 0, 1); - if (sourceBlocks == null) { - throw new IOException( - "Cannot located blocks for source file " + source); - } - String sourceBlockPoolId = - sourceBlocks.getLastLocatedBlock().getBlock().getBlockPoolId(); - if (!sourceBlockPoolId.equals(targetBlockPoolId)) { - throw new IOException("Cannot concatenate source file " + source - + " because it is located in a different namespace" - + " with block pool id " + sourceBlockPoolId - + " from the target file with block pool id " - + targetBlockPoolId); - } + // Concat only effects when all files in same namespace. And in router view, a file only exists in one RemoteLocation. + final List locations = + rpcServer.getLocationsForPath(trg, true); + if (locations == null) { + throw new IOException("Cannot find target file - " + trg); } - // Find locations in the matching namespace. - final RemoteLocation targetDestination = - rpcServer.getLocationForPath(trg, true, targetBlockPoolId); + final RemoteLocation targetDestination = locations.get(0); + String targetNameService = targetDestination.getNameserviceId(); + String[] sourceDestinations = new String[src.length]; for (int i = 0; i < src.length; i++) { String sourceFile = src[i]; - RemoteLocation location = - rpcServer.getLocationForPath(sourceFile, true, targetBlockPoolId); - sourceDestinations[i] = location.getDest(); + List srcLocations = + rpcServer.getLocationsForPath(sourceFile, true); + if (srcLocations == null) { + throw new IOException( + "Cannot find source file " + sourceFile); + } + RemoteLocation srcLocation = srcLocations.get(0); + sourceDestinations[i] = srcLocation.getDest(); + if (!targetNameService.equals(srcLocation.getNameserviceId())) { + throw new IOException("Cannot concatenate source file " + sourceFile + + " because it is located in a different namespace" + + " with nameservice " + srcLocation.getNameserviceId() + + " from the target file with nameservice " + + targetNameService); + } } // Invoke RemoteMethod method = new RemoteMethod("concat", diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java index fe1323c4b5fe1..217c62ff28762 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterRpcServer.java @@ -1697,42 +1697,6 @@ public Long getNextSPSPath() throws IOException { return nnProto.getNextSPSPath(); } - /** - * Locate the location with the matching block pool id. - * - * @param path Path to check. - * @param failIfLocked Fail the request if locked (top mount point). - * @param blockPoolId The block pool ID of the namespace to search for. - * @return Prioritized list of locations in the federated cluster. - * @throws IOException if the location for this path cannot be determined. - */ - protected RemoteLocation getLocationForPath( - String path, boolean failIfLocked, String blockPoolId) - throws IOException { - - final List locations = - getLocationsForPath(path, failIfLocked); - - String nameserviceId = null; - Set namespaces = - this.namenodeResolver.getNamespaces(); - for (FederationNamespaceInfo namespace : namespaces) { - if (namespace.getBlockPoolId().equals(blockPoolId)) { - nameserviceId = namespace.getNameserviceId(); - break; - } - } - if (nameserviceId != null) { - for (RemoteLocation location : locations) { - if (location.getNameserviceId().equals(nameserviceId)) { - return location; - } - } - } - throw new IOException( - "Cannot locate a nameservice for block pool " + blockPoolId); - } - /** * Get the possible locations of a path in the federated cluster. * During the get operation, it will do the quota verification. diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java index 766a035151c2a..ecaef98f0a27b 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java @@ -1224,6 +1224,17 @@ public void testProxyConcatFile() throws Exception { String badPath = "/unknownlocation/unknowndir"; compareResponses(routerProtocol, nnProtocol, m, new Object[] {badPath, new String[] {routerFile}}); + + // Test when concat trg is a empty file + createFile(routerFS, existingFile, existingFileSize); + String sameRouterEmptyFile = + cluster.getFederatedTestDirectoryForNS(sameNameservice) + + "_newemptyfile"; + createFile(routerFS, sameRouterEmptyFile, 0); + // Concat in same namespaces, succeeds + testConcat(existingFile, sameRouterEmptyFile, false); + FileStatus mergedStatus = getFileStatus(routerFS, sameRouterEmptyFile); + assertEquals(existingFileSize, mergedStatus.getLen()); } @Test From 7b8c582c6534f80e7d98b33f9602c412ad5df6a5 Mon Sep 17 00:00:00 2001 From: lgh Date: Thu, 2 May 2024 15:40:19 +0800 Subject: [PATCH 2/9] triggle compile From 382c3f81247edcd4ac66967439aea5402acb20c7 Mon Sep 17 00:00:00 2001 From: lgh Date: Mon, 6 May 2024 10:45:32 +0800 Subject: [PATCH 3/9] Fix SpotBugs Report --- .../server/federation/router/RouterClientProtocol.java | 7 ------- 1 file changed, 7 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index 075ad346b7dfa..e2814377fdaab 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -670,9 +670,6 @@ public void concat(String trg, String[] src) throws IOException { // Concat only effects when all files in same namespace. And in router view, a file only exists in one RemoteLocation. final List locations = rpcServer.getLocationsForPath(trg, true); - if (locations == null) { - throw new IOException("Cannot find target file - " + trg); - } final RemoteLocation targetDestination = locations.get(0); String targetNameService = targetDestination.getNameserviceId(); @@ -682,10 +679,6 @@ public void concat(String trg, String[] src) throws IOException { String sourceFile = src[i]; List srcLocations = rpcServer.getLocationsForPath(sourceFile, true); - if (srcLocations == null) { - throw new IOException( - "Cannot find source file " + sourceFile); - } RemoteLocation srcLocation = srcLocations.get(0); sourceDestinations[i] = srcLocation.getDest(); if (!targetNameService.equals(srcLocation.getNameserviceId())) { From 0aa6a1e016efbc5cfc3498c24b3d9ae705cfaf7f Mon Sep 17 00:00:00 2001 From: lgh Date: Mon, 6 May 2024 10:48:13 +0800 Subject: [PATCH 4/9] Fix checkstyle --- .../hdfs/server/federation/router/RouterClientProtocol.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index e2814377fdaab..95c61d5a17244 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -667,7 +667,8 @@ public void rename2(final String src, final String dst, public void concat(String trg, String[] src) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.WRITE); - // Concat only effects when all files in same namespace. And in router view, a file only exists in one RemoteLocation. + // Concat only effects when all files in same namespace. + // And in router view, a file only exists in one RemoteLocation. final List locations = rpcServer.getLocationsForPath(trg, true); From e1fea88ce11670322a73d6d20f1e61f93ba7783b Mon Sep 17 00:00:00 2001 From: lgh Date: Fri, 10 May 2024 18:24:39 +0800 Subject: [PATCH 5/9] get first right file for mulitple file with different nameservice --- .../router/RouterClientProtocol.java | 42 +++++++++++++------ 1 file changed, 29 insertions(+), 13 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index 95c61d5a17244..8749083348075 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -667,26 +667,28 @@ public void rename2(final String src, final String dst, public void concat(String trg, String[] src) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.WRITE); - // Concat only effects when all files in same namespace. - // And in router view, a file only exists in one RemoteLocation. - final List locations = - rpcServer.getLocationsForPath(trg, true); - - final RemoteLocation targetDestination = locations.get(0); - String targetNameService = targetDestination.getNameserviceId(); + // Concat only effects when all files in the same namespace. + RemoteResult trgResult = getFileRemoteResult(trg); + if (trgResult.getResult() == null) { + throw new IOException("Cannot find target file - " + trg); + } + RemoteLocation targetDestination = trgResult.getLocation(); + String targetNameService = trgResult.getLocation().getNameserviceId(); String[] sourceDestinations = new String[src.length]; for (int i = 0; i < src.length; i++) { String sourceFile = src[i]; - List srcLocations = - rpcServer.getLocationsForPath(sourceFile, true); - RemoteLocation srcLocation = srcLocations.get(0); + RemoteResult srcResult = getFileRemoteResult(sourceFile); + if (srcResult.getResult() == null) { + throw new IOException("Cannot find source file - " + sourceFile); + } + RemoteLocation srcLocation = srcResult.getLocation(); sourceDestinations[i] = srcLocation.getDest(); + if (!targetNameService.equals(srcLocation.getNameserviceId())) { throw new IOException("Cannot concatenate source file " + sourceFile - + " because it is located in a different namespace" - + " with nameservice " + srcLocation.getNameserviceId() - + " from the target file with nameservice " + + " because it is located in a different namespace" + " with nameservice " + + srcLocation.getNameserviceId() + " from the target file with nameservice " + targetNameService); } } @@ -998,6 +1000,20 @@ public HdfsFileStatus getFileInfo(String src) throws IOException { return ret; } + public RemoteResult getFileRemoteResult(String path) + throws IOException { + rpcServer.checkOperation(NameNode.OperationCategory.READ); + + final List locations = rpcServer.getLocationsForPath(path, false, false); + RemoteMethod method = + new RemoteMethod("getFileInfo", new Class[] {String.class}, new RemoteParam()); + // Check for file information sequentially + RemoteResult result = + rpcClient.invokeSequential(method, locations, HdfsFileStatus.class, null); + + return result; + } + @Override public boolean isFileClosed(String src) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.READ); From acc81392df1ebeb5567c816ad549ce5e81313a99 Mon Sep 17 00:00:00 2001 From: lgh Date: Sat, 11 May 2024 18:53:26 +0800 Subject: [PATCH 6/9] add getFileRemoteLocation function && add test case for a src empty src --- .../router/RouterClientProtocol.java | 36 +++++++++++-------- .../federation/router/TestRouterRpc.java | 8 +++++ 2 files changed, 29 insertions(+), 15 deletions(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index 8749083348075..78bbecd490f80 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -106,6 +106,7 @@ import java.net.ConnectException; import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.EnumSet; import java.util.HashMap; @@ -668,21 +669,19 @@ public void concat(String trg, String[] src) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.WRITE); // Concat only effects when all files in the same namespace. - RemoteResult trgResult = getFileRemoteResult(trg); - if (trgResult.getResult() == null) { + RemoteLocation targetDestination = getFileRemoteLocation(trg); + if (targetDestination == null) { throw new IOException("Cannot find target file - " + trg); } - RemoteLocation targetDestination = trgResult.getLocation(); - String targetNameService = trgResult.getLocation().getNameserviceId(); + String targetNameService = targetDestination.getNameserviceId(); String[] sourceDestinations = new String[src.length]; for (int i = 0; i < src.length; i++) { String sourceFile = src[i]; - RemoteResult srcResult = getFileRemoteResult(sourceFile); - if (srcResult.getResult() == null) { + RemoteLocation srcLocation = getFileRemoteLocation(sourceFile); + if (srcLocation == null) { throw new IOException("Cannot find source file - " + sourceFile); } - RemoteLocation srcLocation = srcResult.getLocation(); sourceDestinations[i] = srcLocation.getDest(); if (!targetNameService.equals(srcLocation.getNameserviceId())) { @@ -1000,18 +999,25 @@ public HdfsFileStatus getFileInfo(String src) throws IOException { return ret; } - public RemoteResult getFileRemoteResult(String path) - throws IOException { + public RemoteLocation getFileRemoteLocation(String path) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.READ); final List locations = rpcServer.getLocationsForPath(path, false, false); - RemoteMethod method = - new RemoteMethod("getFileInfo", new Class[] {String.class}, new RemoteParam()); - // Check for file information sequentially - RemoteResult result = - rpcClient.invokeSequential(method, locations, HdfsFileStatus.class, null); + if (locations.size() == 1) + return locations.get(0); + RemoteLocation remoteLocation = null; + for (RemoteLocation location : locations) { + RemoteMethod method = + new RemoteMethod("getFileInfo", new Class[] {String.class}, new RemoteParam()); + HdfsFileStatus ret = rpcClient.invokeSequential(Collections.singletonList(location), method, + HdfsFileStatus.class, null); + if (ret != null) { + remoteLocation = location; + break; + } + } - return result; + return remoteLocation; } @Override diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java index ecaef98f0a27b..a3d3e57077fc4 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java @@ -1235,6 +1235,14 @@ public void testProxyConcatFile() throws Exception { testConcat(existingFile, sameRouterEmptyFile, false); FileStatus mergedStatus = getFileStatus(routerFS, sameRouterEmptyFile); assertEquals(existingFileSize, mergedStatus.getLen()); + + // Test when concat srclist has some empty file, namenode will throw IOException. + String srcEmptyFile = cluster.getFederatedTestDirectoryForNS(sameNameservice) + "_srcEmptyFile"; + createFile(routerFS, srcEmptyFile, 0); + String targetFile = cluster.getFederatedTestDirectoryForNS(sameNameservice) + "_targetFile"; + createFile(routerFS, targetFile, existingFileSize); + // Concat in same namespaces, succeeds + testConcat(srcEmptyFile, targetFile, true); } @Test From 61d08c583e427df3340a7afcd984ad69943a1675 Mon Sep 17 00:00:00 2001 From: lgh Date: Mon, 13 May 2024 09:49:54 +0800 Subject: [PATCH 7/9] test for verify exception msg with empty src file --- .../federation/router/TestRouterRpc.java | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java index a3d3e57077fc4..048babda19362 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java @@ -1163,6 +1163,21 @@ public void testProxyGetPreferedBlockSize() throws Exception { routerProtocol, nnProtocol, m, new Object[] {badPath}); } + private void testConcat( + String source, String target, boolean failureExpected, boolean verfiyException, String msg) { + boolean failure = false; + try { + // Concat test file with fill block length file via router + routerProtocol.concat(target, new String[] {source}); + } catch (IOException ex) { + failure = true; + if (verfiyException) { + assertExceptionContains(msg, ex); + } + } + assertEquals(failureExpected, failure); + } + private void testConcat( String source, String target, boolean failureExpected) { boolean failure = false; @@ -1242,7 +1257,8 @@ public void testProxyConcatFile() throws Exception { String targetFile = cluster.getFederatedTestDirectoryForNS(sameNameservice) + "_targetFile"; createFile(routerFS, targetFile, existingFileSize); // Concat in same namespaces, succeeds - testConcat(srcEmptyFile, targetFile, true); + testConcat(srcEmptyFile, targetFile, true, true, + "concat: source file " + srcEmptyFile + " is invalid or empty or underConstruction"); } @Test From 0c3ea013638be3e91a7972c80cf694a1447ea1a0 Mon Sep 17 00:00:00 2001 From: lgh Date: Mon, 13 May 2024 18:14:09 +0800 Subject: [PATCH 8/9] fix code style --- .../hdfs/server/federation/router/RouterClientProtocol.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java index 78bbecd490f80..d50648219050f 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/main/java/org/apache/hadoop/hdfs/server/federation/router/RouterClientProtocol.java @@ -1003,8 +1003,9 @@ public RemoteLocation getFileRemoteLocation(String path) throws IOException { rpcServer.checkOperation(NameNode.OperationCategory.READ); final List locations = rpcServer.getLocationsForPath(path, false, false); - if (locations.size() == 1) + if (locations.size() == 1) { return locations.get(0); + } RemoteLocation remoteLocation = null; for (RemoteLocation location : locations) { RemoteMethod method = From 7a591b04da617ed30dab681782dc378af6ce527c Mon Sep 17 00:00:00 2001 From: lgh Date: Mon, 13 May 2024 21:23:10 +0800 Subject: [PATCH 9/9] add expection msg for test case --- .../hadoop/hdfs/server/federation/router/TestRouterRpc.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java index 048babda19362..c84dd2ceb2060 100644 --- a/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java +++ b/hadoop-hdfs-project/hadoop-hdfs-rbf/src/test/java/org/apache/hadoop/hdfs/server/federation/router/TestRouterRpc.java @@ -1258,7 +1258,8 @@ public void testProxyConcatFile() throws Exception { createFile(routerFS, targetFile, existingFileSize); // Concat in same namespaces, succeeds testConcat(srcEmptyFile, targetFile, true, true, - "concat: source file " + srcEmptyFile + " is invalid or empty or underConstruction"); + "org.apache.hadoop.ipc.RemoteException(org.apache.hadoop.HadoopIllegalArgumentException): concat: source file " + + srcEmptyFile + " is invalid or empty or underConstruction"); } @Test