HDFS-8541. Mover should exit with NO_MOVE_PROGRESS if there is no move progress. Contributed by Surendra Singh Lilhore

This commit is contained in:
Tsz-Wo Nicholas Sze 2015-07-13 15:12:26 -07:00
parent f7c8311e98
commit 9ef03a4c5b
4 changed files with 43 additions and 7 deletions

View File

@ -716,6 +716,9 @@ Release 2.8.0 - UNRELEASED
HDFS-8751. Remove setBlocks API from INodeFile and misc code cleanup. (Zhe
Zhang via jing9)
HDFS-8541. Mover should exit with NO_MOVE_PROGRESS if there is no move
progress. (Surendra Singh Lilhore via szetszwo)
OPTIMIZATIONS
HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than

View File

@ -317,6 +317,7 @@ public class Dispatcher {
sendRequest(out, eb, accessToken);
receiveResponse(in);
nnc.getBytesMoved().addAndGet(block.getNumBytes());
target.getDDatanode().setHasSuccess();
LOG.info("Successfully moved " + this);
} catch (IOException e) {
LOG.warn("Failed to move " + this + ": " + e.getMessage());
@ -500,6 +501,7 @@ public class Dispatcher {
/** blocks being moved but not confirmed yet */
private final List<PendingMove> pendings;
private volatile boolean hasFailure = false;
private volatile boolean hasSuccess = false;
private final int maxConcurrentMoves;
@Override
@ -573,6 +575,10 @@ public class Dispatcher {
void setHasFailure() {
this.hasFailure = true;
}
void setHasSuccess() {
this.hasSuccess = true;
}
}
/** A node that can be the sources of a block move */
@ -964,6 +970,18 @@ public class Dispatcher {
}
}
/**
* @return true if some moves are success.
*/
public static boolean checkForSuccess(
Iterable<? extends StorageGroup> targets) {
boolean hasSuccess = false;
for (StorageGroup t : targets) {
hasSuccess |= t.getDDatanode().hasSuccess;
}
return hasSuccess;
}
/**
* Decide if the block is a good candidate to be moved from source to target.
* A block is a good candidate if

View File

@ -269,10 +269,14 @@ public class Mover {
// wait for pending move to finish and retry the failed migration
boolean hasFailed = Dispatcher.waitForMoveCompletion(storages.targets
.values());
if (hasFailed) {
boolean hasSuccess = Dispatcher.checkForSuccess(storages.targets
.values());
if (hasFailed && !hasSuccess) {
if (retryCount.get() == retryMaxAttempts) {
throw new IOException("Failed to move some block's after "
result.setRetryFailed();
LOG.error("Failed to move some block's after "
+ retryMaxAttempts + " retries.");
return result;
} else {
retryCount.incrementAndGet();
}
@ -713,10 +717,12 @@ public class Mover {
private boolean hasRemaining;
private boolean noBlockMoved;
private boolean retryFailed;
Result() {
hasRemaining = false;
noBlockMoved = true;
retryFailed = false;
}
boolean isHasRemaining() {
@ -735,16 +741,25 @@ public class Mover {
this.noBlockMoved = noBlockMoved;
}
void setRetryFailed() {
this.retryFailed = true;
}
/**
* @return SUCCESS if all moves are success and there is no remaining move.
* @return NO_MOVE_PROGRESS if no progress in move after some retry. Return
* SUCCESS if all moves are success and there is no remaining move.
* Return NO_MOVE_BLOCK if there moves available but all the moves
* cannot be scheduled. Otherwise, return IN_PROGRESS since there
* must be some remaining moves.
*/
ExitStatus getExitStatus() {
return !isHasRemaining() ? ExitStatus.SUCCESS
: isNoBlockMoved() ? ExitStatus.NO_MOVE_BLOCK
: ExitStatus.IN_PROGRESS;
if (retryFailed) {
return ExitStatus.NO_MOVE_PROGRESS;
} else {
return !isHasRemaining() ? ExitStatus.SUCCESS
: isNoBlockMoved() ? ExitStatus.NO_MOVE_BLOCK
: ExitStatus.IN_PROGRESS;
}
}
}

View File

@ -404,7 +404,7 @@ public class TestMover {
int rc = ToolRunner.run(conf, new Mover.Cli(),
new String[] {"-p", file.toString()});
Assert.assertEquals("Movement should fail after some retry",
ExitStatus.IO_EXCEPTION.getExitCode(), rc);
ExitStatus.NO_MOVE_PROGRESS.getExitCode(), rc);
} finally {
cluster.shutdown();
}