Skip to content

Commit 6fb7e4a

Browse files
committed
HDFS-6079. Timeout for getFileBlockStorageLocations does not work. Contributed by Andrew Wang.
git-svn-id: https://svn.apache.org/repos/asf/hadoop/common/trunk@1576979 13f79535-47bb-0310-9956-ffa450edef68
1 parent cf0b63e commit 6fb7e4a

File tree

6 files changed

+80
-3
lines changed

6 files changed

+80
-3
lines changed

hadoop-hdfs-project/hadoop-hdfs/CHANGES.txt

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -601,6 +601,8 @@ Release 2.4.0 - UNRELEASED
601601
HDFS-6086. Fix a case where zero-copy or no-checksum reads were not allowed
602602
even when the block was cached (cmccabe)
603603

604+
HDFS-6079. Timeout for getFileBlockStorageLocations does not work. (wang)
605+
604606
BREAKDOWN OF HDFS-5698 SUBTASKS AND RELATED JIRAS
605607

606608
HDFS-5717. Save FSImage header in protobuf. (Haohui Mai via jing9)

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/BlockStorageLocationUtil.java

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.util.List;
2525
import java.util.Map;
2626
import java.util.concurrent.Callable;
27+
import java.util.concurrent.CancellationException;
2728
import java.util.concurrent.ExecutionException;
2829
import java.util.concurrent.ExecutorService;
2930
import java.util.concurrent.Future;
@@ -158,6 +159,9 @@ static Map<DatanodeInfo, HdfsBlocksMetadata> queryDatanodesForHdfsBlocksMetadata
158159
try {
159160
HdfsBlocksMetadata metadata = future.get();
160161
metadatas.put(callable.getDatanodeInfo(), metadata);
162+
} catch (CancellationException e) {
163+
LOG.info("Cancelled while waiting for datanode "
164+
+ datanode.getIpcAddr(false) + ": " + e.toString());
161165
} catch (ExecutionException e) {
162166
Throwable t = e.getCause();
163167
if (t instanceof InvalidBlockTokenException) {

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/DFSClient.java

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1224,7 +1224,8 @@ public BlockStorageLocation[] getBlockStorageLocations(
12241224
getConf().connectToDnViaHostname);
12251225

12261226
if (LOG.isTraceEnabled()) {
1227-
LOG.trace("metadata returned: " + Joiner.on("\n").withKeyValueSeparator("=").join(metadatas));
1227+
LOG.trace("metadata returned: "
1228+
+ Joiner.on("\n").withKeyValueSeparator("=").join(metadatas));
12281229
}
12291230

12301231
// Regroup the returned VolumeId metadata to again be grouped by

hadoop-hdfs-project/hadoop-hdfs/src/main/java/org/apache/hadoop/hdfs/server/datanode/DataNode.java

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1159,6 +1159,9 @@ public HdfsBlocksMetadata getHdfsBlocksMetadata(
11591159
checkBlockToken(new ExtendedBlock(bpId, blockIds[i]),
11601160
tokens.get(i), BlockTokenSecretManager.AccessMode.READ);
11611161
}
1162+
1163+
DataNodeFaultInjector.get().getHdfsBlocksMetadata();
1164+
11621165
return data.getHdfsBlocksMetadata(bpId, blockIds);
11631166
}
11641167

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,38 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one
3+
* or more contributor license agreements. See the NOTICE file
4+
* distributed with this work for additional information
5+
* regarding copyright ownership. The ASF licenses this file
6+
* to you under the Apache License, Version 2.0 (the
7+
* "License"); you may not use this file except in compliance
8+
* with the License. You may obtain a copy of the License at
9+
*
10+
* http://www.apache.org/licenses/LICENSE-2.0
11+
*
12+
* Unless required by applicable law or agreed to in writing, software
13+
* distributed under the License is distributed on an "AS IS" BASIS,
14+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15+
* See the License for the specific language governing permissions and
16+
* limitations under the License.
17+
*/
18+
package org.apache.hadoop.hdfs.server.datanode;
19+
20+
import com.google.common.annotations.VisibleForTesting;
21+
22+
import org.apache.hadoop.classification.InterfaceAudience;
23+
24+
/**
25+
* Used for injecting faults in DFSClient and DFSOutputStream tests.
26+
* Calls into this are a no-op in production code.
27+
*/
28+
@VisibleForTesting
29+
@InterfaceAudience.Private
30+
public class DataNodeFaultInjector {
31+
public static DataNodeFaultInjector instance = new DataNodeFaultInjector();
32+
33+
public static DataNodeFaultInjector get() {
34+
return instance;
35+
}
36+
37+
public void getHdfsBlocksMetadata() {}
38+
}

hadoop-hdfs-project/hadoop-hdfs/src/test/java/org/apache/hadoop/hdfs/TestDistributedFileSystem.java

Lines changed: 31 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838
import java.util.EnumSet;
3939
import java.util.List;
4040
import java.util.Random;
41+
import java.util.concurrent.CancellationException;
4142

4243
import org.apache.commons.lang.ArrayUtils;
4344
import org.apache.commons.logging.impl.Log4JLogger;
@@ -60,6 +61,7 @@
6061
import org.apache.hadoop.fs.VolumeId;
6162
import org.apache.hadoop.fs.permission.FsPermission;
6263
import org.apache.hadoop.hdfs.MiniDFSCluster.DataNodeProperties;
64+
import org.apache.hadoop.hdfs.server.datanode.DataNodeFaultInjector;
6365
import org.apache.hadoop.hdfs.server.namenode.ha.HATestUtil;
6466
import org.apache.hadoop.hdfs.web.HftpFileSystem;
6567
import org.apache.hadoop.hdfs.web.WebHdfsFileSystem;
@@ -71,6 +73,9 @@
7173
import org.apache.log4j.Level;
7274
import org.junit.Test;
7375
import org.mockito.InOrder;
76+
import org.mockito.Mockito;
77+
import org.mockito.invocation.InvocationOnMock;
78+
import org.mockito.stubbing.Answer;
7479

7580
import com.google.common.base.Supplier;
7681
import com.google.common.collect.Lists;
@@ -782,8 +787,11 @@ public void testGetFileBlockStorageLocationsError() throws Exception {
782787
final Configuration conf = getTestConfiguration();
783788
conf.setBoolean(DFSConfigKeys.DFS_HDFS_BLOCKS_METADATA_ENABLED,
784789
true);
790+
conf.setInt(
791+
DFSConfigKeys.DFS_CLIENT_FILE_BLOCK_STORAGE_LOCATIONS_TIMEOUT_MS, 1500);
785792
conf.setInt(
786793
CommonConfigurationKeysPublic.IPC_CLIENT_CONNECT_MAX_RETRIES_KEY, 0);
794+
787795
MiniDFSCluster cluster = null;
788796
try {
789797
cluster = new MiniDFSCluster.Builder(conf).numDataNodes(2).build();
@@ -828,12 +836,33 @@ public Boolean get() {
828836
List<BlockLocation> allLocs = Lists.newArrayList();
829837
allLocs.addAll(Arrays.asList(blockLocs1));
830838
allLocs.addAll(Arrays.asList(blockLocs2));
831-
839+
840+
// Stall on the DN to test the timeout
841+
DataNodeFaultInjector injector = Mockito.mock(DataNodeFaultInjector.class);
842+
Mockito.doAnswer(new Answer<Void>() {
843+
@Override
844+
public Void answer(InvocationOnMock invocation) throws Throwable {
845+
Thread.sleep(3000);
846+
return null;
847+
}
848+
}).when(injector).getHdfsBlocksMetadata();
849+
DataNodeFaultInjector.instance = injector;
850+
851+
BlockStorageLocation[] locs = fs.getFileBlockStorageLocations(allLocs);
852+
for (BlockStorageLocation loc: locs) {
853+
assertEquals(
854+
"Found more than 0 cached hosts although RPCs supposedly timed out",
855+
0, loc.getCachedHosts().length);
856+
}
857+
858+
// Restore a default injector
859+
DataNodeFaultInjector.instance = new DataNodeFaultInjector();
860+
832861
// Stop a datanode to simulate a failure.
833862
DataNodeProperties stoppedNode = cluster.stopDataNode(0);
834863

835864
// Fetch VolumeBlockLocations
836-
BlockStorageLocation[] locs = fs.getFileBlockStorageLocations(allLocs);
865+
locs = fs.getFileBlockStorageLocations(allLocs);
837866
assertEquals("Expected two HdfsBlockLocation for two 1-block files", 2,
838867
locs.length);
839868

0 commit comments

Comments
 (0)