HDFS-8980. Remove unnecessary block replacement in INodeFile. Contributed by Jing Zhao.
(cherry picked from commit caa04de149
)
This commit is contained in:
parent
0191dae2ec
commit
f39c749f2a
|
@ -520,6 +520,8 @@ Release 2.8.0 - UNRELEASED
|
|||
|
||||
HDFS-8983. NameNode support for protected directories. (Arpit Agarwal)
|
||||
|
||||
HDFS-8980. Remove unnecessary block replacement in INodeFile. (jing9)
|
||||
|
||||
OPTIMIZATIONS
|
||||
|
||||
HDFS-8026. Trace FSOutputSummer#writeChecksumChunks rather than
|
||||
|
|
|
@ -39,7 +39,7 @@ import static org.apache.hadoop.hdfs.server.namenode.INodeId.INVALID_INODE_ID;
|
|||
* the block are stored.
|
||||
*/
|
||||
@InterfaceAudience.Private
|
||||
public abstract class BlockInfo extends Block
|
||||
public abstract class BlockInfo extends Block
|
||||
implements LightWeightGSet.LinkedElement {
|
||||
|
||||
public static final BlockInfo[] EMPTY_ARRAY = {};
|
||||
|
@ -209,12 +209,6 @@ public abstract class BlockInfo extends Block
|
|||
*/
|
||||
abstract boolean removeStorage(DatanodeStorageInfo storage);
|
||||
|
||||
/**
|
||||
* Replace the current BlockInfo with the new one in corresponding
|
||||
* DatanodeStorageInfo's linked list
|
||||
*/
|
||||
abstract void replaceBlock(BlockInfo newBlock);
|
||||
|
||||
/**
|
||||
* Find specified DatanodeStorageInfo.
|
||||
* @return DatanodeStorageInfo or null if not found.
|
||||
|
@ -375,19 +369,12 @@ public abstract class BlockInfo extends Block
|
|||
}
|
||||
|
||||
/**
|
||||
* Convert an under construction block to a complete block.
|
||||
*
|
||||
* @return BlockInfo - a complete block.
|
||||
* @throws IOException if the state of the block
|
||||
* (the generation stamp and the length) has not been committed by
|
||||
* the client or it does not have at least a minimal number of replicas
|
||||
* reported from data-nodes.
|
||||
* Convert an under construction block to complete.
|
||||
*/
|
||||
BlockInfo convertToCompleteBlock() throws IOException {
|
||||
void convertToCompleteBlock() {
|
||||
assert getBlockUCState() != BlockUCState.COMPLETE :
|
||||
"Trying to convert a COMPLETE block";
|
||||
uc = null;
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,19 +104,4 @@ public class BlockInfoContiguous extends BlockInfo {
|
|||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
void replaceBlock(BlockInfo newBlock) {
|
||||
assert newBlock instanceof BlockInfoContiguous;
|
||||
for (int i = this.numNodes() - 1; i >= 0; i--) {
|
||||
final DatanodeStorageInfo storage = this.getStorageInfo(i);
|
||||
final boolean removed = storage.removeBlock(this);
|
||||
assert removed : "currentBlock not found.";
|
||||
|
||||
final DatanodeStorageInfo.AddBlockResult result = storage.addBlock(
|
||||
newBlock);
|
||||
assert result == DatanodeStorageInfo.AddBlockResult.ADDED :
|
||||
"newBlock already exists.";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -640,37 +640,34 @@ public class BlockManager implements BlockStatsMXBean {
|
|||
return false; // already completed (e.g. by syncBlock)
|
||||
|
||||
final boolean b = commitBlock(lastBlock, commitBlock);
|
||||
if(countNodes(lastBlock).liveReplicas() >= minReplication)
|
||||
completeBlock(bc, bc.numBlocks()-1, false);
|
||||
if (countNodes(lastBlock).liveReplicas() >= minReplication) {
|
||||
completeBlock(lastBlock, false);
|
||||
}
|
||||
return b;
|
||||
}
|
||||
|
||||
/**
|
||||
* Convert a specified block of the file to a complete block.
|
||||
* @param bc file
|
||||
* @param blkIndex block index in the file
|
||||
* @throws IOException if the block does not have at least a minimal number
|
||||
* of replicas reported from data-nodes.
|
||||
*/
|
||||
private BlockInfo completeBlock(final BlockCollection bc,
|
||||
final int blkIndex, boolean force) throws IOException {
|
||||
if(blkIndex < 0)
|
||||
return null;
|
||||
BlockInfo curBlock = bc.getBlocks()[blkIndex];
|
||||
if(curBlock.isComplete())
|
||||
return curBlock;
|
||||
private void completeBlock(BlockInfo curBlock, boolean force)
|
||||
throws IOException {
|
||||
if (curBlock.isComplete()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int numNodes = curBlock.numNodes();
|
||||
if (!force && numNodes < minReplication)
|
||||
throw new IOException("Cannot complete block: " +
|
||||
"block does not satisfy minimal replication requirement.");
|
||||
if(!force && curBlock.getBlockUCState() != BlockUCState.COMMITTED)
|
||||
if (!force && numNodes < minReplication) {
|
||||
throw new IOException("Cannot complete block: "
|
||||
+ "block does not satisfy minimal replication requirement.");
|
||||
}
|
||||
if (!force && curBlock.getBlockUCState() != BlockUCState.COMMITTED) {
|
||||
throw new IOException(
|
||||
"Cannot complete block: block has not been COMMITTED by the client");
|
||||
BlockInfo completeBlock = curBlock.convertToCompleteBlock();
|
||||
// replace penultimate block in file
|
||||
bc.setBlock(blkIndex, completeBlock);
|
||||
|
||||
}
|
||||
|
||||
curBlock.convertToCompleteBlock();
|
||||
// Since safe-mode only counts complete blocks, and we now have
|
||||
// one more complete block, we need to adjust the total up, and
|
||||
// also count it as safe, if we have at least the minimum replica
|
||||
|
@ -680,33 +677,18 @@ public class BlockManager implements BlockStatsMXBean {
|
|||
namesystem.adjustSafeModeBlockTotals(0, 1);
|
||||
namesystem.incrementSafeBlockCount(
|
||||
Math.min(numNodes, minReplication));
|
||||
|
||||
// replace block in the blocksMap
|
||||
return blocksMap.replaceBlock(completeBlock);
|
||||
}
|
||||
|
||||
private BlockInfo completeBlock(final BlockCollection bc,
|
||||
final BlockInfo block, boolean force) throws IOException {
|
||||
BlockInfo[] fileBlocks = bc.getBlocks();
|
||||
for(int idx = 0; idx < fileBlocks.length; idx++)
|
||||
if(fileBlocks[idx] == block) {
|
||||
return completeBlock(bc, idx, force);
|
||||
}
|
||||
return block;
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the given block in the given file to be marked as complete,
|
||||
* regardless of whether enough replicas are present. This is necessary
|
||||
* when tailing edit logs as a Standby.
|
||||
*/
|
||||
public BlockInfo forceCompleteBlock(final BlockCollection bc,
|
||||
final BlockInfo block) throws IOException {
|
||||
public void forceCompleteBlock(final BlockInfo block) throws IOException {
|
||||
block.commitBlock(block);
|
||||
return completeBlock(bc, block, true);
|
||||
completeBlock(block, true);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Convert the last block of the file to an under construction block.<p>
|
||||
* The block is converted only if the file has blocks and the last one
|
||||
|
@ -2494,7 +2476,7 @@ public class BlockManager implements BlockStatsMXBean {
|
|||
int numCurrentReplica = countLiveNodes(storedBlock);
|
||||
if (storedBlock.getBlockUCState() == BlockUCState.COMMITTED
|
||||
&& numCurrentReplica >= minReplication) {
|
||||
completeBlock(getBlockCollection(storedBlock), storedBlock, false);
|
||||
completeBlock(storedBlock, false);
|
||||
} else if (storedBlock.isComplete() && result == AddBlockResult.ADDED) {
|
||||
// check whether safe replication is reached for the block
|
||||
// only complete blocks are counted towards that.
|
||||
|
@ -2568,7 +2550,7 @@ public class BlockManager implements BlockStatsMXBean {
|
|||
|
||||
if(storedBlock.getBlockUCState() == BlockUCState.COMMITTED &&
|
||||
numLiveReplicas >= minReplication) {
|
||||
storedBlock = completeBlock(bc, storedBlock, false);
|
||||
completeBlock(storedBlock, false);
|
||||
} else if (storedBlock.isComplete() && result == AddBlockResult.ADDED) {
|
||||
// check whether safe replication is reached for the block
|
||||
// only complete blocks are counted towards that
|
||||
|
|
|
@ -209,20 +209,4 @@ class BlocksMap {
|
|||
int getCapacity() {
|
||||
return capacity;
|
||||
}
|
||||
|
||||
/**
|
||||
* Replace a block in the block map by a new block.
|
||||
* The new block and the old one have the same key.
|
||||
* @param newBlock - block for replacement
|
||||
* @return new block
|
||||
*/
|
||||
BlockInfo replaceBlock(BlockInfo newBlock) {
|
||||
BlockInfo currentBlock = blocks.get(newBlock);
|
||||
assert currentBlock != null : "the block if not in blocksMap";
|
||||
// replace block in data-node lists
|
||||
currentBlock.replaceBlock(newBlock);
|
||||
// replace block in the map itself
|
||||
blocks.put(newBlock);
|
||||
return newBlock;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -506,7 +506,7 @@ public class FSEditLogLoader {
|
|||
}
|
||||
INodeFile oldFile = INodeFile.valueOf(fsDir.getINode(path), path);
|
||||
// add the new block to the INodeFile
|
||||
addNewBlock(fsDir, addBlockOp, oldFile);
|
||||
addNewBlock(addBlockOp, oldFile);
|
||||
break;
|
||||
}
|
||||
case OP_SET_REPLICATION: {
|
||||
|
@ -943,7 +943,7 @@ public class FSEditLogLoader {
|
|||
/**
|
||||
* Add a new block into the given INodeFile
|
||||
*/
|
||||
private void addNewBlock(FSDirectory fsDir, AddBlockOp op, INodeFile file)
|
||||
private void addNewBlock(AddBlockOp op, INodeFile file)
|
||||
throws IOException {
|
||||
BlockInfo[] oldBlocks = file.getBlocks();
|
||||
Block pBlock = op.getPenultimateBlock();
|
||||
|
@ -963,7 +963,7 @@ public class FSEditLogLoader {
|
|||
|
||||
oldLastBlock.setNumBytes(pBlock.getNumBytes());
|
||||
if (!oldLastBlock.isComplete()) {
|
||||
fsNamesys.getBlockManager().forceCompleteBlock(file, oldLastBlock);
|
||||
fsNamesys.getBlockManager().forceCompleteBlock(oldLastBlock);
|
||||
fsNamesys.getBlockManager().processQueuedMessagesForBlock(pBlock);
|
||||
}
|
||||
} else { // the penultimate block is null
|
||||
|
@ -1016,7 +1016,7 @@ public class FSEditLogLoader {
|
|||
if (!oldBlock.isComplete() &&
|
||||
(!isLastBlock || op.shouldCompleteLastBlock())) {
|
||||
changeMade = true;
|
||||
fsNamesys.getBlockManager().forceCompleteBlock(file, oldBlock);
|
||||
fsNamesys.getBlockManager().forceCompleteBlock(oldBlock);
|
||||
}
|
||||
if (changeMade) {
|
||||
// The state or gen-stamp of the block has changed. So, we may be
|
||||
|
|
Loading…
Reference in New Issue