HDFS-9690. ClientProtocol.addBlock is not idempotent after HDFS-8071.

This commit is contained in:
Tsz-Wo Nicholas Sze 2016-01-26 11:20:13 +08:00
parent 4334976187
commit c59c142f47
3 changed files with 35 additions and 15 deletions

View File

@ -1806,6 +1806,9 @@ Release 2.7.3 - UNRELEASED
HDFS-9672. o.a.h.hdfs.TestLeaseRecovery2 fails intermittently (Mingliang Liu HDFS-9672. o.a.h.hdfs.TestLeaseRecovery2 fails intermittently (Mingliang Liu
via jitendra) via jitendra)
HDFS-9690. ClientProtocol.addBlock is not idempotent after HDFS-8071.
(szetszwo)
Release 2.7.2 - 2016-01-25 Release 2.7.2 - 2016-01-25
INCOMPATIBLE CHANGES INCOMPATIBLE CHANGES

View File

@ -177,17 +177,16 @@ class FSDirWriteFileOp {
src = fsn.dir.resolvePath(pc, src, pathComponents); src = fsn.dir.resolvePath(pc, src, pathComponents);
FileState fileState = analyzeFileState(fsn, src, fileId, clientName, FileState fileState = analyzeFileState(fsn, src, fileId, clientName,
previous, onRetryBlock); previous, onRetryBlock);
final INodeFile pendingFile = fileState.inode;
// Check if the penultimate block is minimally replicated
if (!fsn.checkFileProgress(src, pendingFile, false)) {
throw new NotReplicatedYetException("Not replicated yet: " + src);
}
if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) { if (onRetryBlock[0] != null && onRetryBlock[0].getLocations().length > 0) {
// This is a retry. No need to generate new locations. // This is a retry. No need to generate new locations.
// Use the last block if it has locations. // Use the last block if it has locations.
return null; return null;
} }
final INodeFile pendingFile = fileState.inode;
if (!fsn.checkFileProgress(src, pendingFile, false)) {
throw new NotReplicatedYetException("Not replicated yet: " + src);
}
if (pendingFile.getBlocks().length >= fsn.maxBlocksPerFile) { if (pendingFile.getBlocks().length >= fsn.maxBlocksPerFile) {
throw new IOException("File has reached the limit on maximum number of" throw new IOException("File has reached the limit on maximum number of"
+ " blocks (" + DFSConfigKeys.DFS_NAMENODE_MAX_BLOCKS_PER_FILE_KEY + " blocks (" + DFSConfigKeys.DFS_NAMENODE_MAX_BLOCKS_PER_FILE_KEY

View File

@ -432,19 +432,37 @@ public class TestDFSClientRetries {
// Make the call to addBlock() get called twice, as if it were retried // Make the call to addBlock() get called twice, as if it were retried
// due to an IPC issue. // due to an IPC issue.
doAnswer(new Answer<LocatedBlock>() { doAnswer(new Answer<LocatedBlock>() {
private int getBlockCount(LocatedBlock ret) throws IOException {
LocatedBlocks lb = cluster.getNameNodeRpc().getBlockLocations(src, 0, Long.MAX_VALUE);
assertEquals(lb.getLastLocatedBlock().getBlock(), ret.getBlock());
return lb.getLocatedBlocks().size();
}
@Override @Override
public LocatedBlock answer(InvocationOnMock invocation) throws Throwable { public LocatedBlock answer(InvocationOnMock invocation) throws Throwable {
LocatedBlock ret = (LocatedBlock) invocation.callRealMethod(); LOG.info("Called addBlock: "
LocatedBlocks lb = cluster.getNameNodeRpc().getBlockLocations(src, 0, Long.MAX_VALUE); + Arrays.toString(invocation.getArguments()));
int blockCount = lb.getLocatedBlocks().size();
assertEquals(lb.getLastLocatedBlock().getBlock(), ret.getBlock()); // call first time
// warp NotReplicatedYetException with RemoteException as rpc does.
final LocatedBlock ret;
try {
ret = (LocatedBlock) invocation.callRealMethod();
} catch(NotReplicatedYetException e) {
throw new RemoteException(e.getClass().getName(), e.getMessage());
}
final int blockCount = getBlockCount(ret);
// Retrying should result in a new block at the end of the file. // Retrying should result in a new block at the end of the file.
// (abandoning the old one) // (abandoning the old one)
LocatedBlock ret2 = (LocatedBlock) invocation.callRealMethod(); // It should not have NotReplicatedYetException.
lb = cluster.getNameNodeRpc().getBlockLocations(src, 0, Long.MAX_VALUE); final LocatedBlock ret2;
int blockCount2 = lb.getLocatedBlocks().size(); try {
assertEquals(lb.getLastLocatedBlock().getBlock(), ret2.getBlock()); ret2 = (LocatedBlock) invocation.callRealMethod();
} catch(NotReplicatedYetException e) {
throw new AssertionError("Unexpected exception", e);
}
final int blockCount2 = getBlockCount(ret2);
// We shouldn't have gained an extra block by the RPC. // We shouldn't have gained an extra block by the RPC.
assertEquals(blockCount, blockCount2); assertEquals(blockCount, blockCount2);