Collection<Block> toInvalidate,
Collection<Block> toRetry,
FSNamesystem namesystem) {
// place a deilimiter in the list which separates blocks
// that have been reported from those that have not
BlockInfo delimiter = new BlockInfo(new Block(), 1);
boolean added = this.addBlock(delimiter);
assert added : "Delimiting block cannot be present in the node";
// currently the delimiter is the head
DatanodeIndex indexes = new DatanodeIndex();
indexes.headIndex = 0;
if(newReport == null)
newReport = new BlockListAsLongs( new long[0]);
// scan the report and collect newly reported blocks
// Note we are taking special precaution to limit tmp blocks allocated
// as part this block report - which why block list is stored as longs
Block iblk = new Block(); // a fixed new'ed block to be reused with index i
Block oblk = new Block(); // for fixing genstamps
for (int i = 0; i < newReport.getNumberOfBlocks(); ++i) {
iblk.set(newReport.getBlockId(i), newReport.getBlockLen(i),
newReport.getBlockGenStamp(i));
BlockInfo storedBlock = blocksMap.getStoredBlock(iblk);
if(storedBlock == null) {
// if the block with a WILDCARD generation stamp matches
// then accept this block.
// This block has a diferent generation stamp on the datanode
// because of a lease-recovery-attempt.
oblk.set(newReport.getBlockId(i), newReport.getBlockLen(i),
GenerationStamp.WILDCARD_STAMP);
storedBlock = blocksMap.getStoredBlock(oblk);
if (storedBlock != null && storedBlock.getINode() != null &&
(storedBlock.getGenerationStamp() <= iblk.getGenerationStamp() ||
storedBlock.getINode().isUnderConstruction())) {
// accept block. It wil be cleaned up on cluster restart.
} else {
storedBlock = null;
}
}
if (storedBlock == null) {
// If block is not in blocksMap it does not belong to any file
if (namesystem.getNameNode().shouldRetryAbsentBlock(iblk)) {
toRetry.add(new Block(iblk));
} else {
toInvalidate.add(new Block(iblk));
}
continue;
}
int index = storedBlock.findDatanode(this);
if(index < 0) {// Known block, but not on the DN
// if the size differs from what is in the blockmap, then return
// the new block. addStoredBlock will then pick up the right size of this
// block and will update the block object in the BlocksMap
if (storedBlock.getNumBytes() != iblk.getNumBytes()) {
toAdd.add(new Block(iblk));
} else {
toAdd.add(storedBlock);
}
continue;
}
indexes.currentIndex = index;
// move block to the head of the list
blockList = listMoveToHead(storedBlock, blockList, indexes);
}
// collect blocks that have not been reported
// all of them are next to the delimiter
Iterator<Block> it = new BlockIterator(delimiter.getNext(0), this);
while(it.hasNext()) {
BlockInfo storedBlock = (BlockInfo)it.next();
INodeFile file = storedBlock.getINode();
if (file == null || !file.isUnderConstruction()) {
toRemove.add(storedBlock);
}
}
this.removeBlock(delimiter);